spring boot JPA relation @OneToMany,@ManyToOne

วิธีการทำ Relation ใน JPA ของ Spring boot สมมติเรามี 2 Entity มี Relation กันแบบ OneToMany และ ManyToOne

ขั้นแรกเราต้องทำ Table Relation ใน Database ตัวอย่างคำสั่งนี้เป็นการทำ Foreign key ใน MySQL

ALTER TABLE authentication
ADD FOREIGN KEY (profile_uid)
REFERENCES profile(profile_uid)

สำหรับ 1 Profile มีหลาย Authentication จะต้องใช้ Annonation (@OneToMany) และใช้ @JsonManagedReference สำหรับจัดการไม่ให้เกิด Infinity Loop

@Entity
@Table(name = "profile")
public class Profile {

    //ย้ายพวก @Id, @GeneratedValue, @Column ลงไปอยู่บนหัว method สำหรับการจะทำ JPA Relation
    //for many to one , one to many relation
    //If you move also annotations from id-field
    //to the getId-method (for both entities), problem is solved.

    @JsonProperty("uid")
    private Long uid;

    @JsonProperty("first_name")
    private String firstName;

    @JsonProperty("last_name")
    private String lastName;

    @JsonProperty("display_name")
    private String displayName;

    @Temporal(TemporalType.TIMESTAMP)
    @JsonProperty("birthday")
    private Date birthday;

    @JsonProperty("email")
    private String email;

    @JsonProperty("email_contact")
    private String emailContact;

    @JsonProperty("gender")
    private Long gender;

    @JsonProperty("status")
    private Long status;

    @Temporal(TemporalType.TIMESTAMP)
    @JsonProperty("created_at")
    private Date created_at;

    @JsonProperty("created_ip")
    private String created_ip;

    @Temporal(TemporalType.TIMESTAMP)
    @JsonProperty("updated_at")
    private Date updated_at;

    @JsonProperty("updated_ip")
    private String updated_ip;

    private Set<Authentication> authentications;

    @Id
    @Column(name  = "profile_uid")
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    public Long getUid() {
        return uid;
    }

    public void setUid(Long uid) {
        this.uid = uid;
    }

    @Column(name  = "profile_first_name")
    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    @Column(name  = "profile_last_name")
    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    @Column(name  = "profile_display_name")
    public String getDisplayName() {
        return displayName;
    }

    public void setDisplayName(String displayName) {
        this.displayName = displayName;
    }

    @Column(name  = "profile_birthday")
    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    @Column(name  = "profile_email")
    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    @Column(name  = "profile_email_contact")
    public String getEmailContact() {
        return emailContact;
    }

    public void setEmailContact(String emailContact) {
        this.emailContact = emailContact;
    }

    @Column(name  = "profile_gender")
    public Long getGender() {
        return gender;
    }

    public void setGender(Long gender) {
        this.gender = gender;
    }

    @Column(name  = "profile_status")
    public Long getStatus() {
        return status;
    }

    public void setStatus(Long status) {
        this.status = status;
    }

    @Column(name  = "created_at")
    public Date getCreated_at() {
        return created_at;
    }

    public void setCreated_at(Date created_at) {
        this.created_at = created_at;
    }

    @Column(name  = "created_ip")
    public String getCreated_ip() {
        return created_ip;
    }

    public void setCreated_ip(String created_ip) {
        this.created_ip = created_ip;
    }

    @Column(name  = "updated_at")
    public Date getUpdated_at() {
        return updated_at;
    }

    public void setUpdated_at(Date updated_at) {
        this.updated_at = updated_at;
    }

    @Column(name  = "updated_ip")
    public String getUpdated_ip() {
        return updated_ip;
    }

    public void setUpdated_ip(String updated_ip) {
        this.updated_ip = updated_ip;
    }

    @OneToMany(targetEntity=Authentication.class,mappedBy = "profile",fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JsonManagedReference
    public Set<Authentication> getAuthentications() {
        return authentications;
    }

    public void setAuthentications(Set<Authentication> authentications) {
        this.authentications = authentications;
    }
}

สำหรับ Authentication ที่ผูกกลับไปที่ Profile จะต้องใช้ Annonation (@ManyToOne) และใช้ @JsonBackReference สำหรับจัดการไม่ให้เกิด Infinity Loop

@Entity
@Table(name = "authentication")
public class Authentication {

    //ย้ายพวก @Id, @GeneratedValue, @Column ลงไปอยู่บนหัว method สำหรับการจะทำ JPA Relation
    //for many to one , one to many relation
    //If you move also annotations from id-field
    //to the getId-method (for both entities), problem is solved.

    @JsonProperty("auth_id")
    private Long authId;

    @JsonProperty("account")
    private String account;

    @JsonProperty("client_id")
    private String clientId;

    @JsonProperty("password")
    private String password;

    @JsonProperty("password_oneway")
    private String passwordOneway;

    @JsonProperty("operator")
    private String operator;

    @JsonProperty("status")
    private Long status;

    @Temporal(TemporalType.TIMESTAMP)
    @JsonProperty("verified_date")
    private Date verified_date;

    @JsonProperty("verified_status")
    private Long verified_status;

    @Temporal(TemporalType.TIMESTAMP)
    @JsonProperty("last_login")
    private Date last_login;

    @Temporal(TemporalType.TIMESTAMP)
    @JsonProperty("created_at")
    private Date created_at;

    @JsonProperty("created_ip")
    private String created_ip;

    @Temporal(TemporalType.TIMESTAMP)
    @JsonProperty("updated_at")
    private Date updated_at;

    @JsonProperty("updated_ip")
    private String updated_ip;

    @JsonProperty("auth_type_id")
    private Long auth_type_id;

    @JsonProperty("profile")
    private Profile profile;

    @Column(name  = "client_id")
    public String getClientId() {
        return clientId;
    }

    public void setClientId(String clientId) {
        this.clientId = clientId;
    }

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name  = "auth_id")
    public Long getAuthId() {
        return authId;
    }

    public void setAuthId(Long authId) {
        this.authId = authId;
    }

    @Column(name  = "auth_account")
    public String getAccount() {
        return account;
    }

    public void setAccount(String account) {
        this.account = account;
    }

    @Column(name  = "auth_password")
    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Column(name  = "auth_password_oneway")
    public String getPasswordOneway() {
        return passwordOneway;
    }

    public void setPasswordOneway(String passwordOneway) {
        this.passwordOneway = passwordOneway;
    }

    @Column(name  = "auth_operator")
    public String getOperator() {
        return operator;
    }

    public void setOperator(String operator) {
        this.operator = operator;
    }

    @Column(name  = "auth_status")
    public Long getStatus() {
        return status;
    }

    public void setStatus(Long status) {
        this.status = status;
    }

    @Column(name  = "auth_verified_date")
    public Date getVerified_date() {
        return verified_date;
    }

    public void setVerified_date(Date verified_date) {
        this.verified_date = verified_date;
    }

    @Column(name  = "auth_verified_status")
    public Long getVerified_status() {
        return verified_status;
    }

    public void setVerified_status(Long verified_status) {
        this.verified_status = verified_status;
    }

    @Column(name  = "auth_last_login")
    public Date getLast_login() {
        return last_login;
    }

    public void setLast_login(Date last_login) {
        this.last_login = last_login;
    }

    @Column(name  = "created_at")
    public Date getCreated_at() {
        return created_at;
    }

    public void setCreated_at(Date created_at) {
        this.created_at = created_at;
    }

    @Column(name  = "created_ip")
    public String getCreated_ip() {
        return created_ip;
    }

    public void setCreated_ip(String created_ip) {
        this.created_ip = created_ip;
    }

    @Column(name  = "updated_at")
    public Date getUpdated_at() {
        return updated_at;
    }

    public void setUpdated_at(Date updated_at) {
        this.updated_at = updated_at;
    }

    @Column(name  = "updated_ip")
    public String getUpdated_ip() {
        return updated_ip;
    }

    public void setUpdated_ip(String updated_ip) {
        this.updated_ip = updated_ip;
    }

    @Column(name  = "auth_type_id")
    public Long getAuth_type_id() {
        return auth_type_id;
    }

    public void setAuth_type_id(Long auth_type_id) {
        this.auth_type_id = auth_type_id;
    }

    @ManyToOne
    @JoinColumn(name = "profile_uid")
    @JsonBackReference
    public Profile getProfile() {
        return profile;
    }

    public void setProfile(Profile profile) {
        this.profile = profile;
    }

}

ตัวอย่าง Response เวลาเราเรียก ProfileRepository.findById(1); เราก็จะรู้ว่า profile_uid ที่มีค่า 1 มี authentication อะไรบ้าง

{"authentications":[{"auth_id":7,"account":"kongarn@gmail.com","client_id":"1","password":"9IUoxNtGh52hNaczc9pN0A==","password_oneway":"ee79976c9380d5e337fc1c095ece8c8f22f91f306ceeb161fa51fecede2c4ba1","operator":null,"status":1,"verified_date":null,"verified_status":1,"last_login":null,"created_at":1486314000000,"created_ip":null,"updated_at":null,"updated_ip":null,"auth_type_id":1}],"uid":1,"first_name":"Panupong","last_name":"Kongarn","display_name":"thenesta","birthday":634410000000,"email":"kongarn@gmail.com","email_contact":"kongarn@gmail.com","gender":2,"status":1,"created_at":1485882000000,"created_ip":"127.0.0.1","updated_at":null,"updated_ip":null}

ตัวอย่างวิธีการ save ข้อมูล ตัวอย่างทำการเรียกผ่าน RestController ง่ายๆเลย

@Transactional("transactionManager")
    @RequestMapping(value = "/testsave",  method = { RequestMethod.GET})
    public @ResponseBody
    String testsave(
            @RequestParam Map<String, String> allRequestParams
    ) throws TrueIDException, NoSuchAlgorithmException {
        java.util.Date date = new java.util.Date();

        long time = date.getTime();//timestamp in millisec
        java.sql.Date sqlDate = new java.sql.Date(time);
        java.sql.Time sqlTime = new java.sql.Time(time);

        try {
            Profile profile = new Profile();
            profile.setEmail("test@gmail.com");
            profile.setEmailContact("test@gmail.com");
            profile.setStatus(1L);
            profile.setCreated_ip("127.0.0.1");
            profile.setCreated_at(sqlDate);


            Authentication authentication = new Authentication();
            authentication.setAccount("test@gmail.com");
            authentication.setClientId("1");
            authentication.setProfile(profile);
            authentication.setStatus(1L);
            authentication.setPassword("xxx");
            authentication.setPasswordOneway("xxx");

            Set authentications = new HashSet<Authentication>(){{
                add(authentication);
            }};

            profile.setAuthentications(authentications);

            profileRepository.save(profile);


        } catch (Exception ex) {
            //throw new RuntimeException("Whoop! Somthing went wrong");
        }
        return "OK";
Posted in spring boot | Leave a comment

spring boot logback redis config environment profile

https://github.com/kmtong/logback-redis-appender Import this module to your project or add dependency

Default It write log by using redis rpush command (see in RedisAppender.java). you can change to use redis publish command if you want.

client.rpush(key, json);

setting redis config by environment profile (spring.profiles.active) in /resources/application-alpha.properties
/resources/application-staging.properties
/resources/application-production.properties

logback.redis.ip : localhost
logback.redis.port : 6379

in /resources/logback.xml

<configuration>
    <include resource="logback-${spring.profiles.active}.xml"/>
</configuration>

example in /resources/logback-alpha.xml

<?xml version="1.0" encoding="UTF-8"?>
<included>
    <appender name="redis" class="net.trueid.microservices.logback.RedisAppender">
         <source>mySource</source>
         <sourcePath>mySourcePath</sourcePath>
         <type>otp</type>
         <host>localhost</host>
         <port>6379</port>
         <key>yourkey</key>
    </appender>

    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <pattern>%d{HH:mm:ss.SSS} [%thread] %level %logger - %msg%n</pattern>
        </layout>
    </appender>

    <root level="INFO">
        <appender-ref ref="stdout"/>
        <appender-ref ref="redis"/>
    </root>
</included>

How to write log to redis

private final Logger logger = LoggerFactory.getLogger(RedisAppender.class);
logger.info("your info");

Monitor your log in redis-cli

LINDEX {logback_key} {index}

example run spring boot with spring.actives.profile

spring-boot:run -Dspring.profiles.active=alpha
Posted in java, spring boot | Leave a comment

สอนวิธี live streaming youtube ด้วยโปรแกรม OBS Studio #1

สอนวิธี live stream youtube ด้วยโปรแกรม OBS Studio #1

รายละเอียดในคลิบนี้จะสอนวิธีใช้โปรแกรม OBS Studio ใช้ในการ live streaming ซึ่งสามารถ live ได้ทั้ง twitter , youtube และอื่นๆ นอกจากนี้ยังสอนการ setup audio , การ setup video และนำ key จาก youtube มาผูกกับตัวโปรแกรม

ขอขอบคุณเครดิต พี่แว่น fpsthailand ครับ

Posted in technology | Leave a comment

ชาดาวอินคา ลดพุง ต้านอนุมูลอิสระ ดีต่อสุขภาพ

ชาสมุนไพร ชาดาวอินคา ช่วยลดหน้าท้อง ระงับประสาทบำรุงสมอง ช่วยลดระดับน้ำตาลในเลือด เบาหวาน ลดระดับคอเรสตอรอล ลดความดันโลหิตสูง ช่วยให้นอนหลับดียิ่งขึ้น รสชาติทานแล้วรสคล้ายชาอู่หลง กินชาเป็นประจำรับประกันสุขภาพดีอย่างแน่นอน แต่ให้ระมัดระวังเรื่องคราบชาที่ฟันให้ดี ควรซื้อยาสีฟันสูตรขจัดคราบชาหรือกาแฟมาใช้ด้วย

ชาดาวอินคาต้นกำเนิดมาจากเชียงใหม่ ขึ้นชื่ออยู่แล้ว รออะไรซื้อเลย สุขภาพไม่ได้สร้างกันง่ายๆนะ

Posted in ไม่มีหมวดหมู่ | Leave a comment

data table sorting date format

ใช้ Date Sort – with a hidden element

HTML

<table id="data-table">
   <tr>
     <td><span style="display:none">YYYYMMDD</span>DD/MM/YYYY</td>
   </tr>
</table>

JS

  $('.dataTables-example').DataTable({
                "order": [[ 5, "desc" ]], // 5 is your index of column start with 0
});
Posted in jquery | Leave a comment