XDoclet 与Hibernate 映射
目前,生成POJO的Hibernate映射文件主要有以下三种方式:
①.手动编码、
②.由数据库导出配置文件、
③.XDoclet根据POJO自动生成配置文件。
本人最近研究了XDoclet与Hibernate结合生成映射文件的相关问题,下面就这方面结合《深入浅出Hibernate》8.4节整理成笔记,为方便后来者学习掌握以及与同道中人共同探讨。
原理:
XDoclet在其新版本中,包含了一个为Hibernate提供支持的子类库Hibernate Doclet。
XDoclet实现基本原理是通过在Java代码加入特定的JavaDoc tag,从而为其添加特定的附加语义,之后通过XDoclet工具对代码中JavaDoc Tag进行分析,自动生成与代码对应的配置文件,XDoclet在Hibernate-Doclet中,通过引入Hibernate相关的JavaDoc tag,我们就可以由代码生成对应的Hibernate映射文件。
MyEclipse,Eclipse与XDoclet结合:
MyEclipse和eclipse已经自带了xdoclet,而且已经有了它的各项支持模板。在项目中引入XDoclet的具体的操作很简单:①.点击工程根目录—>点击属性—>选择Myeclipse-xdoclet—>add standard—>standard hibernate,点击应用就可以了。②.再选择工程myeclipse-->run xdoclet 直接生成文件。完成。
例子:
以下是一个POJO代码片断,演示了Hibernate-Doclet的使用方式:
package com.hibernateXDoclet.test.pojo; |
以上是使用Hibernate-Doclet 描述POJO(User)及其对应表(User)之间映射关系的一个例子。其中用到了三个hibernate doclet tag:@hibernate.class、@hibernate.property和@hibernate.id。
这三个tag分别描述了POJO所对应的数据库表信息,以及其字段对应的库表字段信息。之后Hibernate Doclet就会根据这些信息生成映射文件User.hbm.xml:
<?xml version="1.0" encoding="UTF-8"?> <id hibernate-properties-TEmployees.xml |
这样我们只需要维护Java 代码,而无需再手动编写具体的映射文件即可完成Hibernate映射文件代码。
Hibernate Doclet 中常用的Tag:
下面我们就Hibernate Doclet 中常用的Tag 进行探讨,关于Tag 的详细参考,请参见XDoclet 的官方指南:http://xdoclet.sourceforge.net/xdoclet/tags/hibernate-tags.html
及Hibernate Reference: http://www.hibernate.org。
1. Class 层面:
1) @hibernate.class
描述POJO 与数据库表之间的映射关系,并指定相关的运行参数。
参数 |
描述 |
类型 |
必须 |
table |
类对应的表名,默认值:当前类名 |
Text |
N |
dynamic-update |
生成Update SQL时,仅包含发生变动的字段,默认值: false |
Bool |
N |
dynamic-insert |
生成Insert SQL时,仅包含非空(null)字段,默认值:false |
Bool |
N |
Proxy |
代理类,默认值:空 |
Text |
N |
discriminator-value |
子类辨别标识,用于多态支持。 |
Text |
N |
where |
数据甄选条件,如果只需要处理库表中某些特定数据的时候,可通过此选项设定结果集限定条件。如用户表中保存了全国所有用户的数据,而我们的系统只是面向上海用户,则可指定where="location='Shanghai'" |
Text |
N |
典型场景:
/**
* @hibernate.class
* table="TUser" (1)
* dynamic-update="true" (2)
* dynamic-insert="true" (3)
* proxy="" (4)
* discriminator-value="1" (5)
*/
public class TUser implements Serializable {
......
}
本例中:
1 table参数指定了当前类(TUser)对应数据库表"TUser"。
2 dynamic-update 参数设定为生成Update SQL 时候,只包括当前发生变化的字段(提高DB Update性能)。
3 Dynamic-insert 参数设定为生成Insert SQL 时候,只包括当前非空字段。(提高DB Insert性能)
4 Proxy 参数为空,表明当前类不使用代理(Proxy)。代理类的作用是为Lazy.Loading提供支持,请参见下面关于Lazy Loading的有关内容。
5 discriminator-value参数设为"1"。discriminator-value 参数的目的是对多态提供支持。请参见下面关于@hibernate.discriminator的说明。
2) @hibernate.discriminator
@hibernate.discriminator(识别器) 用于提供多态支持。
参数 |
描述 |
类型 |
必须 |
column |
用于区分各子类的字段名称。默认值:当前类名 |
text |
Y |
type |
对应的Hibernate类型 |
Bool |
N |
ength |
字段长度 |
Bool |
N |
如:
TUser类对应数据库表TUser,并且User类有两个派生类SysAdmin、SysOperator。
在TUser表中, 根据user_type字段区分用户类型。
为了让Hibernate根据user_type能自动识别对应的Class类型(如user_type==1则自动映射到SysAdmin类,user_type==2 则自动映射到SysOperator类),我们需要在映射文件中进行配置,而在Hibernate-Doclet中,对应的就是@hibernate.discriminator 标识和 @hibernate.class 以及 @hibernate.subclass 的discriminator-value属性。
典型场景:
/**
*
* @hibernate.class
* table="TUser"
* dynamic-update="true"
* dynamic-insert="true"
*
* @hibernate.discriminator column="user_type" type="integer"
*/
public class TUser implements Serializable {
......
}
根类TUser 中,通过@hibernate.discriminator 指定了以"user_type"字段
作为识别字段。
/**
* @hibernate.subclass
* discriminator-value="1"
*/
public class SysAdmin extends TUser {
......
}
/**
* @hibernate.subclass
* discriminator-value="2"
*/
public class SysOperator extends TUser {
......
}
SysAdmin 和SysOperator 均继承自TUser,其discriminator-value 分别设置
为"1"和"2",运行期Hibernate 在读取t_user 表数据时,会根据其user_type 字段进行判断,如果是1 的话则映射到SysAdmin类,如果是2 映射到SysOperator 类。
上例中,描述SysAdmin 和SysOperator 时,我们引入了一个Tag: @hibernate.subclass,顾名思义,@hibernate.subclass与@hibernate.class
不同之处就在于,@hibernate.subclass 描述的是一个子类,实际上,这两个Tag除去名称不同外,并没有什么区别。
2. Method层面:
1) @hibernate.id
描述POJO 中关键字段与数据库表主键之间的映射关系。
参数 |
描述 |
类型 |
必须 |
column |
主键字段名,默认值:当前类名 |
Text |
N |
type |
字段类型。Hibernate总是使用对象型数据类型作为字段类型,如int对应Integer,因此这里将id设为基本类型[如int]以避免对 |
Text |
N |
length |
字段长度 |
Text |
N |
unsaved-value |
用于对象是否已经保存的判定值。详见"数据访问"章节的相关讨论。 |
Text |
N |
generator-class |
主键产生方式(详见Hibernate QuickStart中关于MiddleGen的相关说明)取值可为下列值中的任意一个:( assigned,hilo,seqhilo, increment, identity, sequence, native, uuid.hex, uuid.string, foreign) |
Text |
Y |
2) @hibernate.property
描述POJO 中属性与数据库表字段之间的映射关系。
参数 |
描述 |
类型 |
必须 |
column |
数据库表字段名,默认值:当前类名 |
Text |
N |
type |
字段类型 |
Text |
N |
length |
字段长度 |
Text |
N |
not-null |
字段是否允许为空 |
Bool |
N |
unique |
字段是否唯一(是否允许重复值) |
Bool |
N |
insert Insert |
操作时是否包含本字段数据,默认:true |
Bool |
N |
update Update |
操作时是否包含本字段数据,默认:true |
Bool |
N |
典型场景:
/**
* @hibernate.property
* column="name"
* length="50"
* not-null="true"
*
* @return String
*/
public String getName() {
return this.name;
}
注意:在编写代码的时候请,对将POJO的getter/setter方法设定为public,如果设定为private,Hibernate将无法对属性的存取进行优化,只能转而采用传统的反射机制进行操作,这将导致大量的性能开销(特别是在1.4之前的Sun JDK版本以及IBM JDK中,反射所带来的系统开销相当可观)。
Notice:*****************如何使用XDoclet生成映射文件
包含XDoclet Tag的代码必须由xdoclet程序进行处理以生成对应的映射文件,
xdoclet的处理模块可通过ant进行加载,下面是一个简单的hibernate xdoclet的ant构建脚本(注意实际使用时需要根据实际情况对路径和CLASSPATH设定进行调整):
<?xml version="1.0"?>
<project name="Hibernate" default="hibernate" basedir=".">
<property name="xdoclet.lib.home" value="C:/xdoclet-1.2.1/lib"/>
<target name="hibernate" depends="" description="Generates Hibernate class descriptor files.">
<taskdef name="hibernatedoclet" classname="xdoclet.modules.hibernate.HibernateDocletTask">
<classpath>
<fileset dir="${xdoclet.lib.home}">
<include name="*.jar"/>
</fileset>
</classpath>
</taskdef>
<hibernatedoclet destdir="./src/" excludedtags="@version,@author,@todo" force="true" verbose="true" mergedir=".">
<fileset dir="./src/">
<include name="**/hibernate/sample/*.java"/>
</fileset>
<hibernate version="2.0"/>
</hibernatedoclet>
</target>
</project>
除了上面我们介绍的Hibernate Doclet Tag,其他还有:
Class层面;
@hibernate.cache
@hibernate.jcs-cache
@hibernate.joined-subclass
@hibernate.joined-subclass-key
@hibernate.query
Method层面
@hibernate.array
@hibernate.bag
@hibernate.collection-cache
@hibernate.collection-composite-element
@hibernate.collection-element
@hibernate.collection-index
@hibernate.collection-jcs-cache
@hibernate.collection-key
@hibernate.collection-key-column
@hibernate.collection-many-to-many
@hibernate.collection-one-to-many
@hibernate.column
@hibernate.component
@hibernate.generator-param
@hibernate.index-many-to-many
@hibernate.list
@hibernate.many-to-one
@hibernate.map
@hibernate.one-to-one
@hibernate.primitive-array
@hibernate.set
@hibernate.timestamp
@hibernate.version
具体的Tag描述请参见XDoclet官方网站提供的Tag说明1。