升级Hibernate5 后主键生成策略调整,hilo调整为table(enhanced-table)

场景描述:因老产品安全测试不能通过,要求第三方依赖组件升级。其中一项是hibernate3.2.7.ga 升级到hibernate5.2.18.Final,产品支持Oracle,Sqlserver,Mysql数据库,此文只记录主键生成策略的调整:从hilo调整为enhanced-table。

hibernate-core-5.2.18.Final.jarorg.hibernate.id.factory.internal.DefaultIdentifierGeneratorFactory.DefaultIdentifierGeneratorFactory()方法可看到hibernate5.2默认支持的所有主键生成策略

/**
	 * Constructs a new DefaultIdentifierGeneratorFactory.
	 */
	@SuppressWarnings("deprecation")
	public DefaultIdentifierGeneratorFactory() {
		register( "uuid2", UUIDGenerator.class );
		register( "guid", GUIDGenerator.class );			// can be done with UUIDGenerator + strategy
		register( "uuid", UUIDHexGenerator.class );			// "deprecated" for new use
		register( "uuid.hex", UUIDHexGenerator.class ); 	// uuid.hex is deprecated
		register( "assigned", Assigned.class );
		register( "identity", IdentityGenerator.class );
		register( "select", SelectGenerator.class );
		register( "sequence", SequenceStyleGenerator.class );
		register( "seqhilo", SequenceHiLoGenerator.class );
		register( "increment", IncrementGenerator.class );
		register( "foreign", ForeignGenerator.class );
		register( "sequence-identity", SequenceIdentityGenerator.class );
		register( "enhanced-sequence", SequenceStyleGenerator.class );
		register( "enhanced-table", TableGenerator.class );
	}

可以看到hibernate5删掉了对hilo主键生成策略的支持。seqhilo和hilo不一样,需要数据库支持序列,mysql不适用。
产品特性要求主键生成策略不能依赖数据库,所以想使用hibernate默认主键生成策略的可选项很窄。hibernate3的时候hilo基本满足此条件,升级到hibernate5之后需要找到一个平滑过渡的主键生成策略替代方案。

以下先回顾hibernate3的时候使用hilo高低位的情况,
hilo的hbm.xml配置:

<hibernate-mapping>
    <class name="com.example.test.className" table="TEST_TABLE">
        <id name="id" type="java.lang.Long">
            <column name="ID" precision="10" scale="0" />
            <generator class="hilo">
                <param name="table">HIBERNATE_UNIQUE_KEY_TEST</param>
                <param name="column">TEST_TABLE</param>
                <param name="max_lo">1000</param>
            </generator>
        </id>
        ...
   </class>
</hibernate-mapping>

同时需要在数据库中需要创建一张名叫HIBERNATE_UNIQUE_KEY_TEST的表,sqlserver 表结构语句如下

CREATE TABLE HIBERNATE_UNIQUE_KEY_TEST (
	ID             NUMERIC (10) NOT NULL,
	TEST_TABLE     NUMERIC (10) NULL,
	TEST_TABLE1    NUMERIC (10) NULL,
	TEST_TABLE2    NUMERIC (10) NULL,
	TEST_TABLE3    NUMERIC (10) NULL,
	PRIMARY KEY (ID)
)

hibernate3的hilo生成策略在sqlserver、mysql数据库下有个问题在此指出:
1、这个hi表(HIBERNATE_UNIQUE_KEY_TEST表)中只放一条数据,按列来记录各表的hi键
2、当多个hbm.xml文件使用同一个表(HIBERNATE_UNIQUE_KEY_TEST)来记录hi值时(如以上表结构中的TEST_TABLE1、TEST_TABLE2列)时,当其中一个hbm.xml对应的表(如TEST_TABLE表)在做频繁的写入大量数据操作时,会使用行级锁锁定行数据修改hi键,这样会影响到别的业务表操作hi键(如TEST_TABLE1、TEST_TABLE2表相关的insert、update语句过来后就会挂起),因为只有一行数据嘛。
避免这种问题出现的办法就是给这种频繁写数据的表单独创建hi表,表与表彼此之间获取主键互不影响。因产品中使用hilo策略的表过多,外加产品开发人员使用hilo时约定不是很清晰,数据库中会出现一堆为其提供hi值的只有一条数据的主键生成策略表,混在业务表中很不优雅。

升级hibernate到5以后发现官方把hilo这种id生成策略给直接摒弃掉了,一方面是惊讶hibernate版本之间兼容性的确较差;另一方面也暗自猜测,hilo生成策略的摒弃可能也和上面给出的原因有关,所以他们设计了新的主键生成策略enhanced-table来弥补这种缺陷。

enhanced-table的使用场景和hilo类似,下面是hibernate5中table主键生成策略的hbm.xml配置事例

<class name="com.example.test.className" table="TEST_TABLE">
		<id name="id" type="java.lang.Long">
            <column name="ID" precision="10" scale="0" />
            <generator class="org.hibernate.id.enhanced.TableGenerator">
                <param name="table_name">HIBERNATE_PK_TABLE</param>
                <param name="value_column_name">GEN_VAL</param>
                <param name="segment_column_name">GEN_PK</param>
                <param name="segment_value">TEST_TABLE</param>
                <param name="increment_size">1</param>
                <param name="optimizer">pooled-lo</param>
        	</generator>
        </id>
        ...
	</class>
</hibernate-mapping>

hibernate5中enhanced-table主键生成策略也需要配合数据库表来使用,以下是表结构

CREATE TABLE HIBERNATE_PK_TABLE (
	GEN_PK  varchar(60) not NULL ,
	GEN_VAL numeric(20,0) NULL 
	PRIMARY KEY (GEN_PK)
) 

和hilo对比table解决了hilo存在的问题:一张HIBERNATE_PK_TABLE表可以按行记录n张表的主键,而不是一行数据按列记录多张表的hi键,所以行级锁就不会影响别的表获取主键了,所以也就不需要设计多张表来存储hi键了

以上简单记录,
后期在实战中使用enhanced-table主键生成策略有新认识的时候再做说明,希望对看到文章,想升级老项目老产品的hibernate的人有所帮助

参考:
https://www.cnblogs.com/linnuo/p/7085688.html
https://blog.csdn.net/qq_35551089/article/details/54861002
https://blog.csdn.net/sun_ting_chuan/article/details/84849053
https://www.cnblogs.com/zhi-leaf/p/6245677.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值