在使用實體類生成對應的數據庫表時,很多的時候都會遇到這種情況:在一個實體類中引用另外的實體類,一般遇上這種情況,我們使用@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