Hibernate-----Hibernate主键生成器

increment

对long、int、short的数据列生成自动增长主键。用于数据库中未把表格主键设置为自增,而又想表格主键自增时

实现机制:在当前应用实例中维持一个变量,以保存着当前的最大值,之后每次需要生成主键的时候将此值加1作为主键

使用范围:若当前有多个实例访问同一个数据库,由于各个实例各自维护主键状态,不同实例可能生成同样的主键,从而造成主键重复异常。因此,若同一数据库有多个实例(也就是并发量大的)问,此方式必须避免使用。 只有在没有其他进程往同一张表中插入数据时才能使用(在集群下不要使用)。但是它的生成标识符机制不依赖于底层数据库系统,所以他适合于所有的数据库系统

identity

对如SQLServer,MySQL等支持自动增长列的数据库,如果数据列的类型是long、short或int,可使用该主键生成器来生成自动增长主键

使用范围:要求底层数据系统必须支持自动增长字段类型。而且它需要底层数据库把主键定义为自动增长字段类型

native

依据底层数据库对自动生成标识符的支持能力,来选择使用identity、sequence或hilo标识符生成器。能自动判断底层数据库提供的生成标识符的机制

使用范围:适合于跨数据库平台开发,即同一个Hibernate应用需要连接多种数据库系统的场合

sequence

对如Oracle,DB2等支持Sequence的数据库,如果数据列的类型是long,short或int,可使用该主键生成器生成自动增长主键。该标识符生成器利用底层数据库提供的序列来生成标识符

<id name="id" column="id">
     <generator class="sequence">
          <!-- 数据库中创建系列userTb_seq -->
          <param name="sequence">userTb_seq</param>
    </generator>
</id>

uuid.hex

由Hibernate基于128 位唯一值产生算法生成16 进制数值(编码后以长度32 的字符串表示)、作为主键

uuid.string

与uuid.hex 类似,只是生成的主键未进行编码(长度16)、。在某些数据库中可能出现问题(如PostgreSQL)、

assigned

主键由外部程序负责生成

<id name="id" column="id">
     <generator class="assigned" />
</id>

hilo

由HIbernate按照一种high/low算法来生成标识符,要在数据库中建立一张额外的表,默认表名(hibernate_unque_key),默认字段(next_hi:integer类型);他从数据库的特定表字段中获取high值;较少用

<id name="id" type="long" column="ID">
         <generator class="hilo">
             <param name="table">hi_value</param>
             <param name="column">next_value</param>
             <param name="max_lo">100</param>
         </generator>
</id>

上例:high值放在hi_value表的next_value字段中

Hibernate 在持久化一个对象时,需要读取并修改hi_value表中的next_value值。这段操作在单独的事务中处理。当save时,不使用当前 session对象的当前数据库联接和事务,而是在一个新的数据库连接中创建新事务,然后访问hi_value表。

适用范围:

适用于所有的数据库系统。

OID必须为long、int或short型,如果定义为byte类型,会抛出异常。

只能在一个数据库中保证标识符唯一

当用户为Hibernate自行提供数据库联接,或者Hibernate通过JTA,从应用服务器的数据源获得数据库联接时无法适用hilo,因为这样不能保证hilo在新的数据库连接的事务中访问hi_value表。在这种情况下,如果数据库系统支持序列,可适用seqhilo生成器。对于支持序列的数据库系统,可适用seqhilo,它从序列中获取high值。

一般而言,利用uuid.hex方式生成主键将提供最好的性能和数据库平台适应性。

另外由于常用的数据库,如Oracle、DB2、SQLServer、MySql 等,都提供了易用的主键生成机制(Auto-Increase 字段或者Sequence)。可在数据库提供的主键生成机制上采用generator-class=native的主键生成方式。不过值得注意的是,一些数据库提供的主键生成机制在效率上未必最佳,大量并发insert数据时可能会引起表之间的互锁。数据库提供的主键生成机制,往往是通过在一个内部表中保存当前主键状态(如对于自增型主键而言,此内部表中就维护着当前的最大值和递增量),之后每次插入数据会读取这个最大值,然后加上递增量作为新记录的主键,之后再把这个新的最大值更新回内部表中,这样,一次Insert操作可能导致数据库内部多次表读写操作,同时伴随的还有数据的加锁解锁操作,这对性能产生了较大影响。因此,对于并发Insert要求较高的系统,推荐采用uuid.hex
作为主键生成机制

foregin

表明直接使用另一个关联的对象的标识属性值(即本持久化对象不能生成主键);这种主键生成器只在基于主键的1-1关联映射中才有用

select

通过数据库触发器选择某个唯一主键的行,并返回其主键值作为标识属性值

自定义主键生成器

主键生成器必须实现  net.sf.hibernate.id.IdentifierGenerator  接口

主键生成类MyIdentifierGenerator

 public class MyIncrementGenerator implements IdentifierGenerator, Configurable{
          private static final Log log = LogFactory.getLog(MyIncrementGenerator.class);
          private long next;
          private String sql;

          public synchronized Serializable generate(SessionImplementor session, Object object)
             throws SQLException, HibernateException {
             if (sql!=null) {
            //获得下一个主键的编号,可以自己定义
            getNext(session.connection());
          }
          return String.valueOf(next);
      }

      public void configure(Type type, Properties params, Dialect d)throws MappingException{
        String table = params.getProperty("table");
        if (table==null)
           table = params.getProperty(PersistentIdentifierGenerator.TABLE);

        String column = params.getProperty("column");

        if (column==null)
           column = params.getProperty(PersistentIdentifierGenerator.PK);

        String schema = params.getProperty(PersistentIdentifierGenerator.SCHEMA);
        returnClass = type.getReturnedClass();

        sql = "select max(to_number(" + column + ")) from " + ( schema==null ? table : schema + '.' + table );
      }

      private void getNext(Connection conn)throws SQLException {
        PreparedStatement st = conn.prepareStatement(sql);
        ResultSet rs = null;
        try {
            rs = st.executeQuery();
            if ( rs.next()) {
                next = rs.getLong(1) + 1;
                if ( rs.wasNull() )
                   next = 1;
            }
            else {
                next = 1;
            }
            sql=null;
            log.debug("first free id: " + next);
        }
        finally {
            if (rs!=null)
               rs.close();
            st.close();
        }
     }

然后再需要使用自定义的主键生成器构造主键的数据库对象所对应的.XML文件中可以这样写:

<id name="uniqueid" column="UNIQUEID" type="string">
        <generator class="com.core.persistence.MyIncrementGenerator"/>
</id>

时间: 2024-09-29 23:31:15

Hibernate-----Hibernate主键生成器的相关文章

Hibernate自定义主键生成器

1:Entity实体配置 2:自定义主键生成器 3:执行save 4:查看结果

Hibernate入门(二)之hibernate的内部执行过程,主键生成器,对象的状态

内部执行过程 主键生成器 Identity(常用) 1.表必须支持自动增长机制 2.数据库生成主键 3.不需要在程序中设置主键 Assigned 必须通过程序的方式给值才可以 person.setId(xxx): 一般用于开发的时候测试使用 Increment(常用) 1.如果选择该主键的生成方式,则必须是数字类型 2.先获取主键的最大值,在最大值的基础上加1,形成新的主键 3.效率比较低,因为这种方式会先select表中最大的主键值 4.主键的生成是由hibernate内部实现的 native

Hibernate主键生成器

主键生成器负责生成数据表记录的主键:increment:为long,short或者int类型主键生成唯一标识.只有在没有其他进程往同一张表中插入数据时才能使用.在集群下不能使用! identity:在DB2,MySQL,Microsoft SQL Server,Sybase和HypersonicSQL等提供identity(自增长)主键支持的数据表中适用.返回的标识属性是long,short或int类型的 sequence:在DB2,PostgreSQL,Oracle,SAP DB,McKoi等

Hibernate各种主键生成策略与配置详解

1.assigned 主键由外部程序负责生成,在 save() 之前必须指定一个.Hibernate不负责维护主键生成.与Hibernate和底层数据库都无关,可以跨数据库.在存储对象前,必须要使用主键的setter方法给主键赋值,至于这个值怎么生成,完全由自己决定,这种方法应该尽量避免. <id name="id" column="id"> <generator class="assigned" /> </id&g

大家一起撸代码之——Hibernate各种主键生成策略与配置详解

1.assigned 主键由外部程序负责生成,在 save() 之前必须指定一个.Hibernate不负责维护主键生成.与Hibernate和底层数据库都无关,可以跨数据库.在存储对象前,必须要使用主键的setter方法给主键赋值,至于这个值怎么生成,完全由自己决定,这种方法应该尽量避免. <id name="id" column="id"> <generator class="assigned" /> </id&g

Hibernate各种主键生成策略与配置详解【附1--&lt;generator class=&quot;foreign&quot;&gt;】

1.assigned 主键由外部程序负责生成,在 save() 之前必须指定一个.Hibernate不负责维护主键生成.与Hibernate和底层数据库都无关,可以跨数据库.在存储对象前,必须要使用主键的setter方法给主键赋值,至于这个值怎么生成,完全由自己决定,这种方法应该尽量避免. <id name="id" column="id"> <generator class="assigned" /> </id&g

从实例看hibernate的主键生成策略

学习了hibernate会发现,hibernate中有实体类,实体类的映射文件,但是我们怎么样才能知道实体类的主键是怎样的生成方式呢?hibernate提供的主键生成策略帮我们完美地解答了这个疑问.下面让我们一起从实例开始认识hibernate的实体生成策略. 一.首先通过User实体类和映射文件的实例 ?User的实体类 package com.bjpowernode.hibernate; import java.util.Set; public class User { private in

Hibernate自定义主键

Hibernate自定义主键,通过此方法可以解决一此特殊的主键ID,在了解自定义主键时,先了解下Hibernate有自带的10种生成主键方法. 1) assigned主键由外部程序负责生成,无需Hibernate参与. 推荐此种方法,在实体配置中修改如下: <id name="HId" type="java.lang.String"> <column name="H_ID" length="20" />

Hibernate各种主键生成策略与配置详解(转)

原文链接:http://www.cnblogs.com/hoobey/p/5508992.html 1.assigned 主键由外部程序负责生成,在 save() 之前必须指定一个.Hibernate不负责维护主键生成.与Hibernate和底层数据库都无关,可以跨数据库.在存储对象前,必须要使用主键的setter方法给主键赋值,至于这个值怎么生成,完全由自己决定,这种方法应该尽量避免. <id name="id" column="id"> <ge

Hibernate各种主键生成策略与配置详解《转》

1.assigned 主键由外部程序负责生成,在 save() 之前必须指定一个.Hibernate不负责维护主键生成.与Hibernate和底层数据库都无关,可以跨数据库.在存储对象前,必须要使用主键的setter方法给主键赋值,至于这个值怎么生成,完全由自己决定,这种方法应该尽量避免. <id name="id" column="id"> <generator class="assigned" /> </id&g