假设我们需要创建一个下面这样的表:
表customers
在其中我们不难发现中间的关于地址的字段有着共性。
HOME_PROVINCE 与 COM_PROVINCE
HOME_STREET 与 COM_STREET
HOME_ZIPCODE 与 COM_ZIPCODE
HOME_CITY 与 COM_CITY
这是一个地址信息在customer中一个是家庭地址,一个是公司地址。这两个有着很强的共性,因此在数据库层和域模型层次我们将其抽象出来一个Address类 ,在Customer类中有两个字段一个家庭地址,一个是公司地址,但是我们不希望另外建立一张地址信息表,一则是提高查询的效率,二者在信息更新或者删除的时候就好似是在一种表上操作甚至是在一张表上,因此在hibernate中也考虑到这一点,于是就有了组件。
下面是代码示例及其解析:
Address.java
Customer.java
无论是增删还是改查Address都会报告异常。
建立精粒度模型的一个重要原则是在不会导致数据冗余的前提下,尽可能的减少数据库表的数目及表的外键参照关系。因为表的外键参照关系很复杂,那么数据库系统在每次对关系数据库进行插入更新查询删除等SQL语句时都必须建立多个表的连接,这是耗时的操作,会影响到数据库的运行的性能。
建立域模型和数据模型有着不同的出发点。与模型是有程序代码组成的,通过细化持久化类的粒度可提高代码的可重用性,简化编程。关系数据模型是由关系数据组成,在存在冗余的情况下,需要把粒度的表拆分成具有外键参照关系的几个细粒度的表,从而节省存储的空间。另外一个方面,在没哟数据冗余的前提下,应该减少表的数目,简化表之间的参照关系,以便提高数据库的访问速度。因此需要从节省空间和节省数据操纵时间这两者进行折中。
这里的Address是一种值类型,值类型与实体类型的一个重要区别是值类型没有OID,不能被单独持久化,它的生命周期依赖于所属的持久化类的对象的生命周期。组件类型就是一种值类型。
<component>元素来映射Customer类的homeAddress和comAddress属性。Adress作为Hibernate组件具有以下明显的特点:
l 没有OID,在数据库中没有对应的表
l 不需要单独创建Adress类的映射文件
l 不能单独持久化Adress对象。Address对象的生命周期依赖于Customer对象的生命周期。
l 其他持久化类不允许关联的Address类
l Address类可以关联其他持久化类
在<component>元素还能嵌套<component>元素,这用于复合组成关系。