这次我们一起来看看Hibernate的ID标识符生成器,也就是Hibernate生成OID有哪些策略!先看下表:
Hibernate标识生成策略
标识符生成器 |
描述 |
increment |
适用于代理主键。由Hibernate自动以递增方式生成。 |
identity |
适用于代理主键。由底层数据库生成标识符。 |
sequence |
适用于代理主键。Hibernate根据底层数据库的序列生成标识符,这要求底层数据库支持序列。 |
hilo |
适用于代理主键。Hibernate分局high/low算法生成标识符。 |
seqhilo |
适用于代理主键。使用一个高/低位算法来高效的生成long,short或者int类型的标识符。 |
native |
适用于代理主键。根据底层数据库对自动生成标识符的方式,自动选择identity、sequence或hilo。 |
uuid.hex |
适用于代理主键。Hibernate采用128位的UUID算法生成标识符。 |
uuid.string |
适用于代理主键。UUID被编码成一个16字符长的字符串。 |
assigned |
适用于自然主键。由Java应用程序负责生成标识符。 |
foreign |
适用于代理主键。使用另外一个相关联的对象的标识符。 |
大家看到,Hibernate提供了很多内置的ID Generator,能很好的满足大多数的应用场景。但开发者可以选择提供自己特定的Generator实现,以满足自己的特定需求——如用更有意义的字符串类型的主键代替整型主键。我们考虑假设有一个user表,主键字段的值我更希望看到的是类似于“U1,U2,U3…”这样更有意义的主键,而不是简单的“1,2,3…”。在数据库中存在大量表,并且表之间的关系较为复杂的情况下,使用有意义的字符串类型的主键能使开发者对表之间的关系更一目了然。
我希望该Generator具有以下功能:
1、 生成的主键是字符串类型。
2、 前缀英文字母或单词可以在配置文件中任意设置。
3、 前缀后面的数字自动增加。
为了实现上述功能,我查看了一下Hibernate所提供的内置的Generator,其中的“hilo”与我要实现的功能较为接近,只不过它返回的是long,short或int,而不是String。看来可以对它稍加改造,于是查看了它的源代码:org.hibernate.id.TableHiLoGenerator。大家可以自己看一下,我就不帖出来了。根据TableHiLoGenerator,很快就完成了我自己的MyGenerator。代码如下:
java 代码
package com.wepull.util;
import java.util.Properties;
import java.io.Serializable;
import org.hibernate.dialect.Dialect;
import org.hibernate.HibernateException;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.id.*;
import org.hibernate.type.*;
import org.hibernate.util.PropertiesHelper;
public class MyGenerator extends TableGenerator {
public static final String PREFIX = "prefix";
private String prefix;
public void configure(Type type, Properties params, Dialect d) {
super.configure(type, params, d);
prefix = PropertiesHelper.getString(PREFIX, params, "");
}
public synchronized Serializable generate(SessionImplementor session,
Object obj) throws HibernateException {
int val = ((Integer) super.generate(session, obj)).intValue();
return prefix + val;
}
}
我只是增加了一个prefix,该前缀的值可以在配置文件中任意指定。下面看看怎样具体使用该Generator: 第一步,在数据库中增加一个表key_generator,在该表中增加一个字段user_id,该字段的类型为Integer,并给该字段一个初始值1。
第二步,写User.hbm.xml配置文件
xml 代码
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping package="com.wepull.pojo">
<class name="User" table="user">
<id name="userId" type="string" column="USER_ID">
<generator class="com.mytest.hibernate.util.MyGenerator">
<param name="table">key_generator</param>
<param name="column">user_id</param>
<param name="prefix">U</param>
</generator>
</id>
...
</class>
</hibernate-mapping>
注意:MyGenerator扩展了TableGenerator类,TableGenerator类由Hibernate提供,它会根据key_generator表中的user_id字段的值来产生下一个整形值。这样我们就得到了“U1,U2,U3,…”主键。
如果我们另外有一个department表,希望产生“D1,D2,D3,…”主健。只需在key_generator表中增加一个整型字段department_id,并给该字段一个初始值1。Department.hbm.xml如下:
xml 代码
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping package="com.wepull.pojo">
<class name="Department" table="department">
<id name="departmentId" type="string" column="DEPARTMENT_ID">
<generator class="com.mytest.hibernate.util.MyGenerator">
<param name="table">key_generator</param>
<param name="column">department_id</param>
<param name="prefix">D</param>
</generator>
</id>
...
</class>
</hibernate-mapping>