精通hibernate学习笔记(5)[映射组成关系]
1、概念
1.1 聚集关系
? 在域模型中,有些类由几个部分类组成,部分类的对象的生命周期依赖于整体类的对象的生命周期,当整体消失时,部分也就随之消失,这种整体与部分的关系被称为聚集关系。
1.2 组成关系
? 如果部分只能属于特定的整体,这种聚集关系也叫做组成关系。
如:任何手足事整体与部分的关系,每双手只能属于特定的人。
2、粒度
建立关系数据模型的一个重要原则:在不会导致数据冗余的前提下,尽可能减少数据库表的数目以及表之间的外键参照关系,这样可以避免建立多表连接。
3. 映射组成关系
建立域模型和关系数据模型有着不同的出发点。域模型是由程序代码组成的,通过细化持久化类的粒度可提高代码可重用性,简化编程。关系数据模型是由关系数据组成的。在存在数据冗余的情况下,需要把粗粒度的表拆分成具有外键参照关系的几个细粒度的表,从而节省存储空间;另一方面,在没有冗余数据的前提下,应该尽可能减少表的数目,简化表之间的参照关系,以便提高数据库的访问速度。
例:
映射文件:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping >
? <class name="mypack.Customer" table="CUSTOMERS" >
??? <id name="id" type="long" column="ID">
????? <generator type="string" >
??????? <column name="NAME" length="15" />
??? </property>
???
??? <component name="homeAddress" />
??????????? <property name="province" type="string" column="HOME_PROVINCE"/>
??????????? <property name="city" type="string" column="HOME_CITY"/>
??????????? <property name="street" type="string" column="HOME_STREET"/>
??????????? <property name="zipcode" type="string" column="HOME_ZIPCODE"/>
??? </component>
???????
??? <component name="comAddress" />
?????????? <property name="province" type="string" column="COM_PROVINCE"/>
?????????? <property name="city" type="string" column="COM_CITY"/>
?????????? <property name="street" type="string" column="COM_STREET"/>
?????????? <property name="zipcode" type="string" column="COM_ZIPCODE"/>
??? </component>
? </class>
</hibernate-mapping>
<component>元素表明homeAddress属性是Customer类的一个组成部分,在hibernate中称之为组件.
<parent>子元素指定Address类所属的整体类,应定义为Address中的一个属性,同时对应的getter、setter方法。
<property>子元素用来配置组件类的属性和表的字段的映射。
3.1 区分值(Value)类型和实体(Entity)类型
上面Address类的定义如下:
package mypack;
import java.io.Serializable;
import org.apache.commons.lang.builder.ToStringBuilder;
/** @author Hibernate CodeGenerator */
public class Address implements Serializable {
??? /** nullable persistent field */
??? private String province;
??? /** nullable persistent field */
??? private String city;
??? /** nullable persistent field */
??? private String street;
??? /** nullable persistent field */
??? private String zipcode;
??? /** nullable persistent field */
??? private mypack.Customer customer;
??? /** full constructor */
??? public Address(String province, String city, String street, String zipcode, mypack.Customer customer) {
??????? this.province = province;
??????? this.city = city;
??????? this.street = street;
??????? this.zipcode = zipcode;
??????? this.customer = customer;
??? }
??? /** default constructor */
??? public Address() {
??? }
??? public String getProvince() {
??????? return this.province;
??? }
??? public void setProvince(String province) {
??????? this.province = province;
??? }
??? public String getCity() {
??????? return this.city;
??? }
??? public void setCity(String city) {
??????? this.city = city;
??? }
??? public String getStreet() {
??????? return this.street;
??? }
??? public void setStreet(String street) {
??????? this.street = street;
??? }
??? public String getZipcode() {
??????? return this.zipcode;
??? }
??? public void setZipcode(String zipcode) {
??????? this.zipcode = zipcode;
??? }
??? public mypack.Customer getCustomer() {
??????? return this.customer;
??? }
??? public void setCustomer(mypack.Customer customer) {
??????? this.customer = customer;
??? }
??? public String toString() {
??????? return new ToStringBuilder(this)
??????????? .toString();
??? }
}
可以发现Address类没有OID,这是Hibernate组件的一个重要特征,没有OID也就不能通过Session来单独管理,否则会抛出MappingException。
??? 持久化类分为两种,值类型和实体类型,最重要的区别是前者没有OID,不能被单独持久化,他的生命周期依赖于所属的持久化类对象的生命周期,组件类型就是一种值类型。
4、映射复合组成关系
配置:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping >
? <class name="mypack.Computer" table="COMPUTERS" >
??? <id name="id" type="long" column="ID">
????? <generator type="string" >
??????? <column name="COMPUTER_TYPE" length="15" />
??? </property>
???
??? <component name="cpuBox" />
???????????
??????????? <property name="type" type="string" >
??????????????? <column name="CPUBOX_TYPE" length="15" />
??????????? </property>
???????????
??????????? <component name="graphicsCard" />
?????????????
?????????????? <property name="type" type="string" >
????????????????? <column name="GRAPHICSCARD_TYPE" length="15" />
?????????????? </property>
??????????? </component>
??????????? <many-to-one
??????????????? name="vendor"
??????????????? column="CPUBOX_VENDOR_ID"
???????????????
??????????? />
??? </component>
? </class>
</hibernate-mapping>
定义:
package mypack;
import java.io.Serializable;
import org.apache.commons.lang.builder.ToStringBuilder;
/** @author Hibernate CodeGenerator */
public class Computer implements Serializable {
??? /** identifier field */
??? private Long id;
??? /** nullable persistent field */
??? private String type;
??? /** persistent field */
??? private mypack.CpuBox cpuBox;
??? /** full constructor */
??? public Computer(String type, mypack.CpuBox cpuBox) {
??????? this.type = type;
??????? this.cpuBox = cpuBox;
??? }
??? /** default constructor */
??? public Computer() {
??? }
??? /** minimal constructor */
??? public Computer(mypack.CpuBox cpuBox) {
??????? this.cpuBox = cpuBox;
??? }
??? public Long getId() {
??????? return this.id;
??? }
??? public void setId(Long id) {
??????? this.id = id;
??? }
??? public String getType() {
??????? return this.type;
??? }
??? public void setType(String type) {
??????? this.type = type;
??? }
??? public mypack.CpuBox getCpuBox() {
??????? return this.cpuBox;
??? }
??? public void setCpuBox(mypack.CpuBox cpuBox) {
??????? this.cpuBox = cpuBox;
??? }
??? public String toString() {
??????? return new ToStringBuilder(this)
??????????? .append("id", getId())
??????????? .toString();
??? }
}
package mypack;
import java.io.Serializable;
import org.apache.commons.lang.builder.ToStringBuilder;
/** @author Hibernate CodeGenerator */
public class CpuBox implements Serializable {
??? /** nullable persistent field */
??? private String type;
??? /** nullable persistent field */
??? private mypack.Computer computer;
??? /** persistent field */
??? private mypack.Vendor vendor;
??? /** persistent field */
??? private mypack.GraphicsCard graphicsCard;
??? /** full constructor */
??? public CpuBox(String type, mypack.Computer computer, mypack.Vendor vendor, mypack.GraphicsCard graphicsCard) {
??????? this.type = type;
??????? this.computer = computer;
??????? this.vendor = vendor;
??????? this.graphicsCard = graphicsCard;
??? }
??? /** default constructor */
??? public CpuBox() {
??? }
??? /** minimal constructor */
??? public CpuBox(mypack.Vendor vendor, mypack.GraphicsCard graphicsCard) {
??????? this.vendor = vendor;
??????? this.graphicsCard = graphicsCard;
??? }
??? public String getType() {
??????? return this.type;
??? }
??? public void setType(String type) {
??????? this.type = type;
??? }
??? public mypack.Computer getComputer() {
??????? return this.computer;
??? }
??? public void setComputer(mypack.Computer computer) {
??????? this.computer = computer;
??? }
??? public mypack.Vendor getVendor() {
??????? return this.vendor;
??? }
??? public void setVendor(mypack.Vendor vendor) {
??????? this.vendor = vendor;
??? }
??? public mypack.GraphicsCard getGraphicsCard() {
??????? return this.graphicsCard;
??? }
??? public void setGraphicsCard(mypack.GraphicsCard graphicsCard) {
??????? this.graphicsCard = graphicsCard;
??? }
??? public String toString() {
??????? return new ToStringBuilder(this)
??????????? .toString();
??? }
}
?