Mapping collections of value types (from 《hibernate in action》chapter 6)
这里所举的例子,都是基于这样的一个情景,Item中包含有Images。
<set name="images" lazy="true" table="ITEM_IMAGE">
<key column="ITEM_ID"/>
<element type="string" column="FILENAME" not-null="true"/>
</set>
这里的<key>定义了外键ITEM_ID,<elememt>则声明了集合的内部数据元素。<set>定义的集合中不可以有重复的数据。
<idbag name="images" lazy="true" table="ITEM_IMAGE">
<collection-id type="long" column="ITEM_IMAGE_ID">
<generator class="sequence"/>
</collection-id>
<key column="ITEM_ID"/>
<element type="string" column="FILENAME" not-null="true"/>
</idbag>
ITEM_IMAGE_ID为主键,而ITEM_ID则为外键,<element>元素不变,这就允许集合中的数据重复。
<list name="images" lazy="true" table="ITEM_IMAGE">
<key column="ITEM_ID"/>
<index column="POSITION"/>
<element type="string" column="FILENAME" not-null="true"/>
</list>
这里为ITEM_IMAGE表添加了index,整个表的主键是ITEM_ID和POSITION构成的复合主键,它允许集合中的数据根据POSITION进行排序。
<map name="images"
lazy="true"
table="ITEM_IMAGE"
sort="natural">
<key column="ITEM_ID"/>
<index column="IMAGE_NAME" type="string"/>
<element type="string" column="FILENAME" not-null="true"/>
</map>
这里为ITEM_IMAGE表添加了index,整个表的主键是ITEM_ID和POSITION构成的复合主键,它允许集合中的数据根据sort指定的内容进行排序,这里允许用户对sort进行定制。
<map name="images"
lazy="true"
table="ITEM_IMAGE"
order-by="IMAGE_NAME asc">
<key column="ITEM_ID"/>
<index column="IMAGE_NAME" type="string"/>
<element type="string" column="FILENAME" not-null="true"/>
</map>
这里采用的是orbder-by,注意sort和order-by的区别。Sort是在内存中使用comparator进行排序,而order-by则是在数据库中使用SQL语句进行排序。
<set name="images"
lazy="true"
table="ITEM_IMAGE"
order-by="IMAGE_NAME asc">
<key column="ITEM_ID"/>
<composite-element class="Image">
<property name="name" column="IMAGE_NAME" not-null="true"/>
<property name="filename" column="FILENAME" not-null="true"/>
<property name="sizeX" column="SIZEX" not-null="true"/>
<property name="sizeY" column="SIZEY" not-null="true"/>
</composite-element>
</set>
这里定义了一个新的Image类,它不是实体类(entity class),而是一个简单的值类型(value type),仅仅是父实体的一个component,其生命周期完全由包含其的父实体 (parent entity) ITEM控制。这里Image类中包含有数据ITEM_ID、 IMAGE_NAME、FILENAME、SIZEX、和SIZEY。
<set name="images"
lazy="true"
table="ITEM_IMAGE"
order-by="IMAGE_NAME asc">
<key column="ITEM_ID"/>
<composite-element class="Image">
<parent name="item"/>
<property name="name" column="IMAGE_NAME" not-null="true"/>
<property name="filename" column="FILENAME" not-null="true"/>
<property name="sizeX" column="SIZEX" not-null="true"/>
<property name="sizeY" column="SIZEY" not-null="true"/>
</composite-element>
</set>
前面定义的IMAGE类中,并不包含有对父实体ITEM的引用。也就是说,只可以从ITEM中导航到IMAGE中,但是在IMAGE无法得到ITEM。这可以通过<parent>实现。这样IMAGE类中就含有一个数据成员item,指向其父实体。
但是,它是无法做到真正的双向导航的。例如:通过SQL查询直接得到IMAGE后,但是如同普通的值类型一样,IMAGE对象的item是null,你无法从component如此直接得到其父对象,这必须由通过父-子关系的entity完成。