说明
在之前的学习中,表格的一列对应Entity的一个属性。数据库表格的列都是比较简单的类型,由此也限制了属性也只能是简单的类型。本文将学习利用@Embeddable 实现多个类映射到复杂类型。
多个列映射到类
数据表格结构:
CREATE TABLE `Person` (
`PersonId` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`FirstName` varchar(60) COLLATE utf8_unicode_ci NOT NULL,
`LastName` varchar(60) COLLATE utf8_unicode_ci NOT NULL,
`PhoneNumber_CountryCode` varchar(5) COLLATE utf8_unicode_ci NOT NULL,
`PhoneNumber_Number` varchar(15) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`PersonId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
其中列PhoneNumber_CountryCode和PhoneNumber_Number都是和电话相关的信息,我们将其整合到一个类PhoneNumber。
@Embeddable 嵌入类
PhoneNumber是Entity Person中的一个属性,不是简单的类型,是一个自定的类。
/*【1】@Embeddable标记表明这是Entity的嵌入类,其属性将映射表格的列。
* 由此,这个类也必须在Entity扫描的范围内。
* 当注意,有些列是不能作为嵌入列,即标记@Id的主键和@EmbeddedId */
@Embeddable
public class PhoneNumber {
private String countryCode;
private String number;
//【2】对各类的描述和Entity的一样
@Basic
@Column(name="PhoneNumber_CountryCode")
public String getCountryCode() { ... }
public void setCountryCode(String countryCode) { ... }
@Basic
@Column(name="PhoneNumber_Number")
public String getNumber() { ... }
public void setNumber(String number) { ... }
}
Entity中引入嵌入类作为属性
@Entity
public class Person {
private long id;
private String firstName;
private String lastName;
private PhoneNumber phoneNumber;
...
//【1】很简单,标记@Embeded,表示这个属性的映射需要进一步去分解
@Embedded
public PhoneNumber getPhoneNumber() { ... }
public void setPhoneNumber(PhoneNumber phoneNumber) { ... }
}
多重嵌套
表格增加地址信息
CREATE TABLE `Person` (
`PersonId` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`FirstName` varchar(60) COLLATE utf8_unicode_ci NOT NULL,
`LastName` varchar(60) COLLATE utf8_unicode_ci NOT NULL,
`PhoneNumber_CountryCode` varchar(5) COLLATE utf8_unicode_ci NOT NULL,
`PhoneNumber_Number` varchar(15) COLLATE utf8_unicode_ci NOT NULL,
`Address_Street` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
`Address_City` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
`Address_State` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,
`Address_Country` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
`Address_PostalCode_Code` varchar(10) COLLATE utf8_unicode_ci NOT NULL,
`Address_PostalCode_Suffix` varchar(5) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`PersonId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
我们增加一定难度,Address这个类不仅作为Person的属性,也作为其他Entity属性,但不同表格的列的名字可能会不一样。有或者PostalCode作为其他Entity的属性,由于表格不一样,对应的列的名字也可能不一样。由此,我们可以在Entity中指定,这个层层嵌套对应下去的列名是什么(或者修订为什么)
嵌套的实现
在嵌套类中可以通过@Embedded来说明映射进一步分解。
@Embeddable
public class PostalCode {
private String code;
private String suffix;
@Basic
@Column(name="PostalCode_Code") //假设映射为其他表的列名,非Person表格的列名
public String getCode() { ... }
public void setCode(String code) { ... }
@Basic
@Column(name="PostalCode_Suffix") //假设映射为其他表的列名,非Person表格的列名
public String getSuffix() { ...}
public void setSuffix(String suffix) { ...}
}
@Embeddable
public class Address {
private String street;
private String city;
private String state;
private String country;
private PostalCode postalCode;
... ...
// 通过@Embedded来说明映射进一步分解,根据PostalCode类所指明的方式进行映射。
// 通过@Embedded可以进行层次嵌套
@Embedded
public PostalCode getPostalCode() { ... }
public void setPostalCode(PostalCode postalCode) { ... }
}
在Entity中重新修订映射的列名
@Entity
public class Person {
private long id;
private String firstName;
private String lastName;
private PhoneNumber phoneNumber;
private Address address;
... ...
/* 通过@AttributeOverrides来对映射的列名们进行修订,如果只对一个列名进行修订,可以用@AttributeOverride
(1)原则上我们也可以在Address对属性和列的映射进行修订,但建议不要这样做。
最终和表格真正映射的是Entity,如果修订,应在Entity上。
(2)name是属性,postalCode.code指的标记所在属性(address)的属性postalCode的属性code。
注意address无需说明,因为这就是在其上的标记。 */
@Embedded
@AttributeOverrides(value = {
@AttributeOverride(name = "postalCode.code", column = @Column(name = "Address_PostalCode_Code")),
@AttributeOverride(name = "postalCode.suffix", column = @Column(name = "Address_PostalCode_Suffix"))
})
public Address getAddress() { ... }
public void setAddress(Address address) { ... }
}