Embeddable 物件


假設您設計了一個T_USER表格,當中有id、name、age與email四個欄位,而在Java程式的方面,您原先設計了一個User類別:
...
@Entity
@Table(name="T_USER")
public class User implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String name;
    private int age;
    private String email;

    ........
}

現在假設您基於商務上的設計需求,需要提高物件設計時的精細度,而將email資訊封裝至一個Email物件,讓它攜帶更多資訊或負有特定職責,而User類別變為如下設計:
  • User.java
package onlyfun.caterpillar;

import java.io.Serializable;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="T_USER")
public class User implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
private Long age;

@Embedded
private Email Email;

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Long getAge() {
return age;
}

public void setAge(Long age) {
this.age = age;
}

public Email getEmail() {
return Email;
}

public void setEmail(Email Email) {
this.Email = Email;
}
}

其中Email封裝了郵件位址資訊,為另行設計的一個類別,您必須使用@Embedded標示,表示映射訊息是位於Email之中:
  • Email.java
package onlyfun.caterpillar;

import java.io.Serializable;
import javax.persistence.Basic;
import javax.persistence.Embeddable;

@Embeddable
public class Email implements Serializable {
private String email;

public String getEmail() {
return email;
}

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

public void sendMail() {
System.out.println("Send mail to " + email);
}
}

Email類別上,則使用@Embeddable標示,注意在JPA的規格書中,目前不支援巢狀的嵌入類別,像Email這樣的物件稱之為值類型(value type)物件,它沒有自己的識別(identity),隸屬於某個實體物件,其生命週期跟隨著所隸屬的實體物件,值類型物件通常不會共用。

在儲存時,只要User設定好Email,儲存User物件時,會自動將Email中的屬性儲存至對應的欄位:
        Email mailAddress = new Email();
        mailAddress.setEmail("caterpillar.onlyfun@gmail.com");
       
        User user = new User();
        user.setName("caterpillar");
        user.setAge(new Long(30));
        user.setMailAddress(mailAddress);

        EntityManager entityManager =
                JPAUtil.getEntityManagerFactory().createEntityManager();
        EntityTransaction etx = entityManager.getTransaction();
        etx.begin();
        entityManager.persist(user);
        etx.commit();
        entityManager.close();

而載入User時,也會自動將欄位設定至Email中對應的屬性:
        EntityManager entityManager =
                JPAUtil.getEntityManagerFactory().createEntityManager();
        EntityTransaction etx = entityManager.getTransaction();
        etx.begin();
        User user = entityManager.find(User.class, id);
        etx.commit();
        entityManager.close();
        user.getMailAddress().sendMail();

@Embedded可以搭配@AttributeOverride或@AttributeOverrides一同使用,以重新定義@Embeddable類別中的映射訊息,例如:
    ....
    @Embedded
    @AttributeOverride(name="email", column=@Column(name="CUST_STREET"))

    private Email Email;
    ....