Hibernate中@Embedded和@Embeddable注解


在使用實體類生成對應的數據庫表時,很多的時候都會遇到這種情況:在一個實體類中引用另外的實體類,一般遇上這種情況,我們使用@OneToOne@OneToMany@ManyToOne@ManyToMany這4個注解比較多,但是好奇害死貓,除了這四個有沒有別的使用情況,尤其是一個實體類要在多個不同的實體類中進行使用,而本身又不需要獨立生成一個數據庫表,這就是需要@Embedded@Embeddable的時候了,下面分成4類來說明在一個實體類中引用另外的實體類的情況,具體的數據庫環境是MySQL 5.7。

使用的兩個實體類如下:

Address類

public class Address implements Serializable{
    private static final long serialVersionUID = 8849870114128959929L;

    private String country;
    private String province;
    private String city;
    private String detail;

    //setter、getter
}

 

Person類:

@Entity
public class Person implements Serializable{
    private static final long serialVersionUID = 8849870114127659929L;

    @Id
    @GeneratedValue
    private Long id;

    @Column(nullable = false)
    private String name;

    @Column(nullable = false)
    private Integer age;

    private Address address;

    //setter、getter
}

 

 

1、 兩個注解全不使用

當這兩個注解都不使用時,那么兩個實體類和上面的相同,那么生成的表結構如下: 

Address屬性字段會映射成tinyblob類型的字段,這是用來存儲不超過255字符的二進制字符串的數據類型,顯然我們通常不會這么使用。

2、 只使用@Embeddable

我們在Address實體類上加上@Embeddable注解,變成如下類:

@Embeddable
public class Address implements Serializable{
    private static final long serialVersionUID = 8849870114128959929L;

    private String country;
    private String province;
    private String city;
    private String detail;

    //setter、getter
}

 

 

而Person實體類不變,生成的數據庫表結構如下: 

可以看出這次是把Address中的字段映射成數據庫列嵌入到Person表中了,而這些字段的類型和長度也使用默認值。如果我們在Address中的字段中設置列的相關屬性,則會按照我們設定的值去生成,如下Address類:

@Embeddable
public class Address implements Serializable{
    private static final long serialVersionUID = 8849870114128959929L;

    @Column(nullable = false)
    private String country;
    @Column(length = 30)
    private String province;
    @Column(unique = true)
    private String city;
    @Column(length = 50)
    private String detail;
    //setter、getter
}

 

 

生成的表結構如下:

 

我們在Address中配置的屬性全部成功映射到Person表中。

3、 只使用@Embedded

這里我們只在Person中使用@Embedded,如下:

@Entity
public class Person implements Serializable{
    private static final long serialVersionUID = 8849870114127659929L;

    @Id
    @GeneratedValue
    private Long id;

    @Column(nullable = false)
    private String name;

    @Column(nullable = false)
    private Integer age;

    @Embedded
    private Address address;

    //setter、getter
}

 

 

Adddress類和最開始的不同POJO類相同,此時生成的表結構如下: 

可以看出這個表結構和在Address中只使用@Embeddable注解時相同,在進入深一步試驗,我們在Address中加入列屬性,但是不使用@Embeddable注解會發生什么? 
Address類如下:

public class Address implements Serializable{
    private static final long serialVersionUID = 8849870114128959929L;

    @Column(nullable = false)
    private String country;
    @Column(length = 30)
    private String province;
    @Column(unique = true)
    private String city;
    @Column(length = 50)
    private String detail;
    //setter、getter
}

 

 

生成數據表結構如下: 

所以只使用@Embedded和只使用@Embeddable產生的效果是相同的。

4、 兩個注解全使用

既然單獨使用@Embedded或者只使用@Embeddable都會產生作用,那么這兩個都使用效果也一定是一樣的,我們平時也是這么用的。所以在這部分我們就不演示和上面相同的效果了,而是說兩個深入的話題。

4.1 覆蓋@Embeddable類中字段的列屬性

這里就要使用另外的兩個注解@AttributeOverrides@AttributeOverride,這兩個注解是用來覆蓋@Embeddable類中字段的屬性的。

  • @AttributeOverrides:里面只包含了@AttributeOverride類型數組;
  • @AttributeOverride:包含要覆蓋的@Embeddable類中字段名name和新增的@Column字段的屬性;

使用如下: 
Person類如下:

@Entity
public class Person implements Serializable{
    private static final long serialVersionUID = 8849870114127659929L;

    @Id
    @GeneratedValue
    private Long id;

    @Column(nullable = false)
    private String name;

    @Column(nullable = false)
    private Integer age;

    @Embedded
    @AttributeOverrides({@AttributeOverride(name="country", column=@Column(name = "person_country", length = 25, nullable = false)),
                        @AttributeOverride(name="city", column = @Column(name = "person_city", length = 15))})
    private Address address;

    //setter、getter
}

 

 

Address類如下:

@Embeddable
public class Address implements Serializable{
    private static final long serialVersionUID = 8849870114128959929L;

    @Column(nullable = false)
    private String country;
    @Column(length = 30)
    private String province;
    @Column(unique = true)
    private String city;
    @Column(length = 50)
    private String detail;
    //setter、getter
}

 

 

生成的數據表如下:

可以看出我們的@AttributeOverrides@AttributeOverride兩個注解起作用了。

4.2 多層嵌入實體類屬性

上面所有的例子都是使用兩層實體類嵌入,其實這種實體類的嵌入映射是可以使用多層的,具體的例子如下。 
我們新建立一個類Direction表示方位如下:

@Embeddable
public class Direction implements Serializable{

    @Column(nullable = false)
    private Integer longitude;
    private Integer latitude;
}

 

 

Address如下:

@Embeddable
public class Address implements Serializable{
    private static final long serialVersionUID = 8849870114128959929L;

    @Column(nullable = false)
    private String country;
    @Column(length = 30)
    private String province;
    @Column(unique = true)
    private String city;
    @Column(length = 50)
    private String detail;

    @Embedded
    private Direction direction;
}

 

Person類如下:

@Entity
public class Person implements Serializable{
    private static final long serialVersionUID = 8849870114127659929L;

    @Id
    @GeneratedValue
    private Long id;

    @Column(nullable = false)
    private String name;

    @Column(nullable = false)
    private Integer age;

    @Embedded
    @AttributeOverrides({@AttributeOverride(name="direction.latitude", column=@Column(name = "person_latitude")),
                        @AttributeOverride(name="direction.longitude", column = @Column(name = "person_longitude"))})
    private Address address;
}

 

 

生成的數據表如下:

在上面需要注意如下幾點:

  • 在Person中定義Direction中的屬性時,需要用”.”將所有相關的屬性連接起來;
  • 在Direction中longitude屬性定義為not null,但是由於使用了@AttributeOverride注解,其中雖然沒有定義null屬性,但是這時使用的是默認的nullable屬性,默認為true;

 

轉載於:http://blog.csdn.net/lmy86263/article/details/52108130

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM