1、increment标识符生成器
由Hibernate以递增的方式为代理主键,例如:
<hibernate-mapping>
<class name="mypack.IncrementTester" table="INCREMENT_TESTER" >
<id name="id" type="long" column="ID" >
<meta attribute="scope-set">private</meta>
<generator class="increment" />
</id>
<property name="name" type="string">
<column name="NAME" length="15" />
</property>
</class>
</hibernate-mapping>
Hibernate在持久化一个IncrementTester对象时,会以递增的方式生成标识符,事实上,Hibernate在初始化阶段读取INCREMENT_TESTER表中最大主键值,接下来向INCREMENT_TESTER表中插入记录时,就在max(ID)基础上递增,增量为1。下面考虑有两个Hibernate应用进程访问同一个数据库的情景。
(1)假定第一个进程中的Hibernate在初始化阶段读取INCREMENT_TESTER表中最大主键为6
(2)第二个进程中的Hibernate在初始化阶段读取INCREMENT_TESTER表中最大主键仍然为6
(3)接下来两个进程中的Hibernate各自向INCREMENT_TESTER表中插入主键为7的记录,这违反了数据库完整性约束,导致有一个进程的插入操作失败。
由此看见,increment标识符生成器仅仅在单个Hibernate应用进程访问数据库的情况下才能有效工作。更确切的说,即使在同一个进程中创建了连接同一个数据库的多个SessionFactory实例,也会导致插入操作失效。在J2EE软件架构中,Hibernate通常作为JNDI资源运行在应用服务器上。
increment标识符生成器具有以下适用范围:
1、由于increment生成标识符的机制不依赖于底层数据库系统,因此他适用于所有的数据库系统
2、适用于只有单个Hibernate应用进程访问同一个数据库的场合,在集群环境下不推荐使用
3、OID必须为long,int或short类型,如果把OID定义为byte类型,在运行时会抛出以下异常:
[java] net.sf.hibernate.id.IdentifierGenerationException:this id generator generates long,integer,short,identity
2、identity标识符生成器
identity标识符生成器由底层数据库来负责生成标识符,他要求底层数据库把主键定义为自动增长字段类型。例如:在Mysql中,应该把主键定义为auto_increment类型,在MS SQL Service中,应该把主键定义为identity类型。配置如下:
<hibernate-mapping>
<class name="mypack.IncrementTester" table="INCREMENT_TESTER" >
<id name="id" type="long" column="ID" >
<meta attribute="scope-set">private</meta>
<generator class="identity" />
</id>
<property name="name" type="string">
<column name="NAME" length="15" />
</property>
</class>
</hibernate-mapping>
Hibernate在持久化一个identityTester对象时,由底层数据库负责生成主键
identity标识符生成器具有以下使用范围。
1、由于identity生成标识符的机制依赖于底层数据库系统,因此,要求底层数据库系统必须支持自动增长字段类型。支持的数据库有DB2、Mysql、Ms SQL Server、Sybase、HSQLDB和Informix等
2、OID必须为long,int或short类型,如果把OID定义为byte在运行时会抛出以下异常
[java] net.sf.hibernate.id.IdentifierGenerationException:this id generator generates long,integer,short,identity
3、sequence标识符生成器
sequence标识符生成器利用底层数据提供的序列来生成标识符,例如:
<hibernate-mapping>
<class name="mypack.IncrementTester" table="INCREMENT_TESTER" >
<id name="id" type="long" column="ID" >
<meta attribute="scope-set">private</meta>
<generator class="sequence">
<param name="sequence">tester_id_seq</param>
</generator>
</id>
<property name="name" type="string">
<column name="NAME" length="15" />
</property>
</class>
</hibernate-mapping>
Hibernate在持久化一个SequenceTester对象时,先从底层数据库的tester_id_seq序列中获得一个唯一的序列号,再把它作为主键值。
sequence标识符生成器具有以下使用范围:
1、由于sequence生成标识符机制依赖于底层数据库系统的序列,因此,要求底层数据库系统必须支持序列,支持的数据库有Oracle、DB2、SAP DB和PostgreSQL等
2、OID必须为long、int或short类型,如果把OID定义为byte类型,在运行时会报出如下异常:
[java] net.sf.hibernate.id.IdentifierGenerationException:this id generator generates long,integer,short,identity
4、Hilo标识符生成器
Hilo标识符生成器由Hibernate按照一定high/low算法来生成标识符,他从数据库的特定表的字段中获取high值,例如如下配置声明使用Hilo标识符生成器,其中high值存放在hi_value表的next_value字段中:
<hibernate-mapping>
<class name="mypack.IncrementTester" table="INCREMENT_TESTER" >
<id name="id" type="long" column="ID" >
<meta attribute="scope-set">private</meta>
<generator class="hilo">
<param name="table">hi_value</param>
<param name="column">next_value</param>
<param name="max_lo">100</param>
</generator>
</id>
<property name="name" type="string">
<column name="NAME" length="15" />
</property>
</class>
</hibernate-mapping>
Hibernate在持久化一个HiloTester对象时,由Hibernate负责生成主键。Hilo标识符生成器在生成标识符时,需要读取并修改hi_value表中的next_value。这段操作需要在单独的事务中处理,例如以下代码中,当执行session.save(object)方法时,Hilo标识符生成器不适用Session对象的当前数据库连接和事务,而是在一个新的数据库连接中创建新的事务,然后访问hi_value表
tx = session.beginTransaction();
session.save(object);
tx.commit();
Hilo标识符生成器具有以下适用范围:
1、由于Hilo生成标识符的机制不依赖于底层数据库系统,因此适用于所有的数据库系统
2、OID必须为long、int或short类型,如果把OID定义为byte类型,在运行时会抛出如下异常:
[java] net.sf.hibernate.id.IdentifierGenerationException:this id generator generates long,integer,short,identity
3、high/low算法生成的标识符只能在一个数据库中保证唯一
4、当用户为Hibernate自行提供数据库连接,或者Hibernate通过JTA,从而应用服务器的数据源获得数据库连接的时候无法使用Hilo,因为这不能保证Hilo在新的数据库连接事务中访问hi_value,在这种情况下,如果数据库系统支持序列,可以使用sehilo生成器。,例如oracle
5、native标识符生成器
native标识符生成器依据底层数据库对自动生成标识符的支持能力,来选择使用identity、sequence或Hilo标识符生成器。native能自动判断底层数据库提供的生成标识符的机制。例如,如果Mysql和MS SQL Server,就选择identity标识符生成器;如果为Oracle,就选择sequence标识符生成器。例如:
<hibernate-mapping>
<class name="mypack.IncrementTester" table="INCREMENT_TESTER" >
<id name="id" type="long" column="ID" >
<meta attribute="scope-set">private</meta>
<generator class="native" />
</id>
<property name="name" type="string">
<column name="NAME" length="15" />
</property>
</class>
</hibernate-mapping>
当底层数据库为Mysql时,其实使用的是identity标识符生成器,因此,当Hibernate在持久化一个NativeTester对象时,由底层数据库负责生成主键值。native标识符生成器具有以下适用范围:
1、由于native能根据底层数据库系统的类型自动选择合适的标识符生成器,因此很适合于夸数据库平台开发,即同一个Hibernate应用需要连接多种数据库系统的场合。
2、OID必须为long、int或short类型,如果把OID定义为byte类型,在运行时会抛出如下异常:
[java] net.sf.hibernate.id.IdentifierGenerationException:this id generator generates long,integer,short,identity