上篇详解了Hibernate继承关系,这篇我们来研究一下复合主键映射和component映射。
一、复合主键映射
实际应用中,也会时常出现一张表id由多个字段构成,这样的主键就是复合主键。同样的,我们通过实例来理解复合主键映射在Hiberbnate中的使用。
1、建立实体类FianClass和它的主键存放类FianPeriodPK【FianPeriodPK实体中存放了FianClass所有主键字段】
public class FianPeriodPK implements Serializable{ //把主键拿出来,唯一生成一个类 注意:实现序列化接口 ,覆盖hashcode和equals方法 private int fYear; private int fMonth; { public class FianClass { //在class中引入主键相关类,作为这个类的主键 private FianPeriodPK fianPeriod; private Date beginDate; private Date endDate; }
2、配置xml文件
<hibernate-mapping> <class name="com.bjpowernode.hibernate.FianClass" table="t_compone"> <!--复合主键类--> <composite-id name="fianPeriod"> <key-property name="fYear"></key-property> <key-property name="fMonth"></key-property> </composite-id> <!--普通属性--> <property name="beginDate"/> <property name="endDate"/> </class> </hibernate-mapping>
3、Junit测试类编写
<span style="font-family:KaiTi_GB2312;">FianClass f=new FianClass(); //构造复合主键 FianPeriodPK pk=new FianPeriodPK(); pk.setfYear(2001); pk.setfMonth(1); //设置类的主键及其他属性 f.setFianPeriod(pk); f.setBeginDate(new Date()); f.setEndDate(new Date()); session.save(f); //构造复合主键 FianPeriodPK pk=new FianPeriodPK(); pk.setfYear(2001); pk.setfMonth(1); //load中id参数要求序列化 pk==两个字段 FianClass f=(FianClass)session.load(FianClass.class,pk); </span>仔细观察代码,我们不难发现:复合主键映射的一般做法就是将符合主键抽出来,形成一个单独的类,在配置文件中利用<composite-id>标签name为主键类类名,key值为主键类中属性,即FianClass类的两个主键。值得注意的是:这个主键构成的类有两点要求:必须实现Serializable序列化接口,必须覆盖hashCode和equels方法。
二、component映射
oo的常用关系:关联关系中的聚合都不陌生,它是整体和个体之间的关系,即has-a的关系,此时整体与部分之间是可分离的。在Hibernate中我们也看到了聚合的影子。来看属性大多相同的用户和员工类是如何通过聚合关系将实体类细分颗粒化的。
1、建立实体类:
public class Employee { private int id; private String name; private Contact empContact; } public class Userloyee { private int id; private String name; private Contact userContact; }
值类:
public class Contact { private String email; private String add; }
2、配置xml
<hibernate-mapping> <class name="com.bjpowernode.hibernate.Employee" table="t_employee"> <id name="id"> <generator class="native"></generator> </id> <component name="empContact"> <property name="email"></property> <property name="add"></property> </component> </class> </hibernate-mapping> User类同上
3、测试
//建立实体类 User user=new User(); user.setName("zal"); //建立值类,值类通常从属于实体类, Contact userContact=new Contact(); userContact.setAdd("lodon"); userContact.setEmail("zal"); user.setUserContact(userContact); session.save(user);通过上述例子,用户和员工类有较多相同的属性,采用一个值类Contact将两实体类相同的属性抽象出来,通过注入contact属性和利用<component>标签配置,实现了User(Employee)与Contact之间的聚合关系,复用率高的特点。
通过对面向对象中常见关系的总结,我们很容易回忆起OO思想中抽象、继承、复用等等字眼,可见hibernate确实不论是对JDBC数据库的连接、CRUD操作,session的管理,以及实体与表的对应、实体与实体间的关联关系都做了很好的封装,通过xml配置,标签属性的修改,关系复杂的数据库结构也轻松跃然纸上,更方便的是利用特有的hql语句,实现对对象进行操作,更是方便了开发者的编码工作。封装不易,且用且体会它的奥妙。