hibernate继承关系映射大概有5种,这5种继承关系映射里面,我觉得最有效最常用的一种方式非常好.就说说这种吧.先来说说hibernate继承关系什么时候使用.
(1) hibernate继承关系什么时候使用?
很多例子都是说一个动物类,然后是老虎类啊,狮子类啊之类去继承动物类.例子很好,但是实际应用中我根据这个提出了一个完全可行的解决方案,很有成就感!
在项目里面,遇到这样一个问题,大概有30多张表,里面都有共性的字段,每张表都需要走审核流程,如果针对每张表都做相应的审核模块,代码重复不说,那工作量就大了.针对这个就需要用到hibernate继承关系映射了,所有共性的字段都提取出来,把审核模块做成公共的模块!这中间又涉及用到了java反射机制.
(2)开始例子
先把30多张表共性的字段整理出来, id主键字段(String 类型的 主键生成方式是uuid),因为uuid按着计算,据说得300年才能出现重复的数据,300年以后我早就入古了,软件维护找我,嘿嘿,连骨灰都没喽!得了,跑题了.......继续!
共有的字段:
id varchar 32
fileName varchar 100
audState varchar 2
tableName varchar 50 (这个字段存表名,表1的名字table1,就存table1,表2的名字table2,就存table2......反射时候用)
上面是所有表中共有的字段.再拿30多张表中的一张table1表来举例子吧.table1表里面自己特有的字段如下:
isDel varchar 2
fileTypeId int 4
code1 varchar 50
code2 varchar 50
code3 varchar 50
hibenrate继承关系映射开始了
把共有的字段提出来做一个配置文件TcommTable.hbm.xml
<! DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<!--
Mapping file autogenerated by MyEclipse - Hibernate Tools
-->
< hibernate-mapping >
< class name ="com.hibernate.po.TcommTable" abstract ="true" dynamic-insert ="true" >
< id name ="id" type ="string" >
< column name ="id" />
< generator class ="uuid" />
</ id >
< property name ="fileName" type ="string" >
< column name ="fileName" length ="100" />
</ property >
< property name ="audState" type ="string" >
< column name ="audState" length ="2" />
</ property >
< property name ="tableName" type ="string" insert ="false" >
< column name ="tableName" length ="32" />
</ property >
</ class >
</ hibernate-mapping >
上面的配置文件是抽象的abstract ="true" .
要生成相应的po:
public abstract class TcommTable implements Serializable {
private String id;
private String fileName;
private String tableName;
//生成set/get()方法
}
table1表特有的字段生成配置文件和po,都是TcommTable 的子类
table1表的配置文件Table1.hbm.xml
<! DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<!--
Mapping file autogenerated by MyEclipse - Hibernate Tools
-->
< hibernate-mapping >
< union-subclass name ="com.hibernate.po.Table1" table ="Table1" extends ="com.hibernate.po.TcommTable " >
< property name ="isDel" type ="string" >
< column name ="isDel" length ="2" />
</ property >
< column name ="fileTypeId" />
</ property >
< column name ="code1" length ="50" />
</ property >
< column name ="code2" length ="50" />
</ property >
< column name ="code3" length ="50" />
</ property >
</ union-subclass >
</ hibernate-mapping >
table1的po:
public class Table1 extends TcommTable {
private String isDel;
private String fileTypeId;
private String code1;
private String code2;
private String code3;
//生成set/get()方法
}
(2)运用java的反射机制实现模块的共用性
当30多张表公用一个审核模块的时候,把抽象类TcommTable传到审核模块,如何知道这个抽象类是那张具体的表呢?就用到了java反射机制了,因为抽象类无法new出对象来,所以就要用java反射机制.
在审核的action里面实现java的反射机制,主要代码如下:
String tableName = request.getParameter("tableName");
String allName = "com.hibernate.po." + tableName;
TcommTable tomm = (TcommTable) Class.forName(allName).newInstance();
这样,就能得到table1所有的字段(公共字段和table1特有的字段),然后把要审核的内容放进tomm这个对象里面就行了.注意,java反射机制必须要带上类的完整包名,否则反射出错.tableName字段是区分30多张表的识别字段,通过这个字段,hibernate就自动可以判断出是哪个表和相应的类了,然后通过反射就能得到相应类的所有字段了,因为公共字段放在一个抽象类里面,抽象类无法new对象,所以只能通过反射机制来实现了.