声明:该部分内容参考http://blog.csdn.net/gudong2945/article/details/7050196
值对象和实体对象是Hibernate的重要概念,当然在jpa中也有相应的概念,他们在语义上是相同的。常常听
到人们抱怨Hibernate中对象之间的映射关系配置很难,而且经常出现一些莫名奇妙的问题。其真正原因是没有
正确的区分值对象和实体对象而进行了错误的设计(其实很多时候就没有值对象的概念,而在系统中将所有的对
象都归结为了实体)。
1. 什么是值对象?
举个例子:如果你又User类和Address类,对于每个具体的User有对应的Address,当然这个 Address可以
是多个(家庭地址、公司地址)等等。而这些地址只能依赖于User类而存在,并且不存在其他对象对某个具体
Address的引用(此处忽略两个人有同一地址的情况)。这时候Address就是一个值对象。更抽象的,对于一个
实体如何区分是值对象和实体对象主要从以下三点考虑
(1) 是否有一个依赖的生命周期,如果此对象依赖于另一个对象的声明周期,就认为他是有一个依赖的生命周
期的;
(2) 是否需要它们自己的同一性(java中体现为 == 和 equals() 方法,数据库中体现为主键是否相等),就
是说你的代码中会不会去比较两个对象是否具有同一性,在上例中体现为我们永远不会去比较两个地址是否相
等(== 或者 equlas());
(3) 是否需要支持共享引用:如果一个对象有一个依赖的生命周期,不需要它们自己的同一性,并且不必支持
共享引用的话它就是个值类型的对象。
例如:报销单下有报销明细,报销明细就是一个值对象,再如一个商品有它的多张照片,照片就是值对象,更
一般的java中的String,Integer,Double.....都是值对象
2. 为什么要使用值对象?
Hibernate对值对象的的映射提供了特别的支持,如果你有一个一对多的关联,而且你希望在一的一方控制一
切的话,更多情况下多的一方是一个值对象。如果是值对象你可以避免考虑级联更新的问题,孤儿删除的问题
等等,因为Hibernate已经处理了这些问题。
常见值对象集合的映射如下:(以商品和图片(路径)为例)
(1) set:
<set name="images" table="ITEM_IMAGE">
<key column="Item_id"/>
<element type="string" column="filename" not-null="true"/>
</set>
(2) list
<list name="images" table="ITEM_IMAGE">
<key column="Item_id"/>
<list-index column="prosition"/>
<element type="string" column="filename" not-null="true"/>
</set>
(3) map
<map name="images" table="ITEM_IMAGE">
<key column="Item_id"/>
<map-index column="imagename" type="stirng"/>
<element type="string" column="filename" not-null="true"/>
</map>
值对象级联删除示例:(以User和Address为例)
(1) 实体:
public class User {
private long userId;
private String firstname;
private String lastname;
private Collection<Address> addresses = new ArrayList<Address>();
/* 省略Get和Set方法*/
...
}
public class Address {
private long addressId;
private String street;
private String zipcode;
private String city;
/* 省略Get和Set方法*/
...
}
(2) XML:
<hibernate-mapping>
<class name="hibernate.entityObject.one_to_many.foreignKeyAssociations.User"
table="USER">
<id name="userId" type="long">
<column name="USER_ID " />
<generator class="native" />
</id>
<property name="firstname" type="string">
<column name="FIRSTNAME" length="40" />
</property>
<property name="lastname" type="string">
<column name="LASTNAME" length="50" />
</property>
<bag name="addresses" cascade="all-delete-orphan" lazy="false" >
<key column="USER_ID"></key>
<one-to-many
class="hibernate.entityObject.onetomany.foreignKeyAssociations.Address" />
</bag>
</class>
</hibernate-mapping>
<hibernate-mapping>
<class
name="hibernate.entityObject.one_to_many.foreignKeyAssociations.Address"
table="Address">
<id name="addressId " type="long">
<generator class="native" />
</id>
<property name="street" type="string" />
<property name="zipcode" type="string" />
<property name="city" type="string" />
</class>
</hibernate-mapping>