`

自定义主键@TableGenerator重启后新值的问题

 
阅读更多
问题描述:
使用自定义表来构建主键,在每次重启之后的新id总是比定义表里面的gen_val大allocationSize倍。

Model的定义
@Entity
@TableGenerator(name = "rh_sys_portlet",
        table = "rh_sys_tb_generator",
        pkColumnName = "gen_name",
        valueColumnName = "gen_value",
        pkColumnValue = "rh_sys_portlet",
        allocationSize = 5
)
@Table(name = "rh_sys_portlet")
public class RhSysPortlet extends BaseObject implements java.io.Serializable{
   ......
}



问题原因:
org.hibernate.id.MultipleHiLoPerTableGenerator的configure()方法后面:
//hilo config
		maxLo = ConfigurationHelper.getInt(MAX_LO, params, Short.MAX_VALUE);
		returnClass = type.getReturnedClass();

		if ( maxLo >= 1 ) {
			hiloOptimizer = new OptimizerFactory.LegacyHiLoAlgorithmOptimizer( returnClass, maxLo );
		}

当maxLo大于1的时候,就调用new OptimizerFactory.LegacyHiLoAlgorithmOptimizer( returnClass, maxLo ),
这个方法会调用到org.hibernate.id.enhanced.OptimizerFactory
public LegacyHiLoAlgorithmOptimizer(Class returnClass, int incrementSize) {
			super( returnClass, incrementSize );
			if ( incrementSize < 1 )
				throw new HibernateException( "increment size cannot be less than 1" );
			if ( LOG.isTraceEnabled() ) {
				LOG.tracev( "Creating hilo optimizer (legacy) with [incrementSize={0}; returnClass={1}]", incrementSize, returnClass.getName() );
			}
			maxLo = incrementSize;
			lo = maxLo+1;
		}

在这个代码运行之后就到:
@Override
		public synchronized Serializable generate(AccessCallback callback) {
			if ( lo > maxLo ) {
				lastSourceValue = callback.getNextValue();
				lo = lastSourceValue.eq( 0 ) ? 1 : 0;
				hi = lastSourceValue.copy().multiplyBy( maxLo+1 );
			}
			value = hi.copy().add( lo++ );
			return value.makeValue();
		}

方法multiplyBy调用到org.hibernate.id.IdentifierGeneratorHelper
public IntegralDataTypeHolder multiplyBy(long factor) {
			checkInitialized();
			value *= factor;
			return this;
		}

=======================
在org.hibernate.id.MultipleHiLoPerTableGenerator
maxLo = ConfigurationHelper.getInt(MAX_LO, params, Short.MAX_VALUE);可以看到,param里面的MAX_LO值,才出现这个问题。


问题追溯:
那么继续找什么时候初始化这个param?
org.hibernate.id.factory.internal.DefaultIdentifierGeneratorFactory
public IdentifierGenerator createIdentifierGenerator(String strategy, Type type, Properties config);


上面是被org.hibernate.mapping.SimpleValue
public IdentifierGenerator createIdentifierGenerator()
方法调用

在这个方法里面,identifierGeneratorProperties保存有max_lo信息,什么时候设定?
这个类里面有个
public void setIdentifierGeneratorProperties(Properties identifierGeneratorProperties) {
		this.identifierGeneratorProperties = identifierGeneratorProperties;
	}

被org.hibernate.cfg.BinderHelper类的
public static void makeIdGenerator()
调用

IdGenerator gen = mappings.getGenerator( generatorName, localGenerators );
gen里面设定params,然后传给这个方法的params。


最后参考文档:Hibernate Annotations参考文档 http://www.okrs.cn/blog/news/?1027.html, 知道注解加上
    @Id
    @GeneratedValue(strategy = GenerationType.TABLE, generator = "rh_sys_portlet")
    @GenericGenerator(name="rh_sys_portlet", strategy = "seqhilo",
            parameters = {
                    @Parameter(name="max_lo", value = "1")
            }
    )
    @Column(name = "portlet_id", unique = true, nullable = false)
    public Long getPortletId() {
        return this.portletId;
    }

    来设定这个max_lo值,就解决了问题。
分享到:
评论

相关推荐

    表生成器 @TableGenerator

    `@TableGenerator` 是一个JPA(Java Persistence API)注解,用于在实体类中定义自增序列的生成器,主要用于为数据库表中的主键生成唯一的ID。这篇博文链接指向的是一个关于`@TableGenerator` 使用的讨论,虽然具体...

    JPA注解详解

    例如,自定义主键生成器表名和初始值: ```java @TableGenerator(name="empGen", table="ID_GENERATOR", initialValue=100, allocationSize=10) @Entity @Id @GeneratedValue(strategy=GenerationType.TABLE, ...

    spring注解详解

    在一些场景下,如主键生成器的名称难以处理、需要调整分配大小、配置初始值等,`@TableGenerator`提供了灵活的解决方案。 - **name**:指定生成器的名称,必须与`@GeneratedValue`注解中的`generator`属性匹配。 - ...

    hibernate复合主键映射

    为了使这个复合主键能够正确地参与到数据库的关联操作中,我们还需要创建一个对应的`@TableGenerator`,以便为每个复合主键生成一个唯一的序列号。这通常不是必需的,因为复合主键通常是业务逻辑决定的,而不是自增...

    GenerationType.TABLE生成策略

    `@GeneratedValue`注解表明该字段的值应由数据库自动生成,而`@TableGenerator`则提供了关于生成器表的详细信息,如表名、初始值、步长等。下面是一个简单的示例: ```java import javax.persistence.Entity; ...

    JPA学习笔记-EJB-03JPA主键生成策略总结

    - `allocationSize`: 主键值的增量大小,默认为1。 3. **IDENTITY(基于数据库的自增字段)** - **概述**:对于支持`IDENTITY`特性的数据库(如MySQL),可以使用`IDENTITY`策略。这种方式利用了数据库层面的自...

    JPA注解教程

    在此示例中,`employee_gen` 为主键生成器的名称,`ID_GEN` 为表名,`GEN_NAME` 和 `GEN_VAL` 分别为主键生成器表中的主键列和值列的名称。`initialValue` 设置为主键序列的初始值100,`allocationSize` 设置为50,...

    hibernate-annotations-3.3.0.GA

    @Temporal用于时间类型字段的精确控制,@TableGenerator则可以自定义主键生成策略,@GeneratedValue则用于自动生成主键。 3. 支持JPA 1.0规范:3.3.0.GA版本完全支持Java Persistence API 1.0标准,这意味着开发者...

    03_Hibernate&JPA .pptx

    通过`@TableGenerator`可以自定义主键生成表,包括表名、主键列名和值列名。 以上就是Hibernate与JPA的基础知识,它们通过注解驱动的编程模型,极大地简化了Java应用与数据库的交互,降低了开发复杂性,提高了代码...

    jpa批注参考

    `@SequenceGenerator`和`@TableGenerator`则提供了更为灵活的主键生成机制,允许开发者指定序列或表作为主键值的来源。 #### 直接映射批注:`@Basic`, `@Enumerated`, `@Temporal`, `@Lob`, `@Transient` 这些批注...

    HIbernate注解详解(二)

    例如,`@GeneratedValue(strategy = GenerationType.IDENTITY)`意味着主键值由数据库自动生成。 对于字段的映射,`@Column`注解至关重要。它用来指定字段如何映射到数据库表的列上。你可以设置列的名称、长度、是否...

    JPA-2 基本注解

    9. **@TableGenerator**: 用于定义自定义的主键生成器,通常配合@GeneratedValue一起使用,适用于非自动递增的主键策略,例如序列。 这些注解的使用使得开发者能够在Java代码中声明式地完成ORM配置,极大地简化了...

    hibernate注解学习笔记

    `@TableGenerator` 注解用于指定表级别的主键生成策略。 示例代码: ```java @Id @GeneratedValue(strategy = GenerationType.TABLE, generator = "employee_seq") @TableGenerator(name = "employee_seq", table =...

    spring使用心得 java ssh

    "spring中,如果想用自定义主键,则不要设置sequnce.txt"提示我们,在Spring配置Hibernate时,如果希望使用自定义的主键生成策略(例如,使用UUID或者自增字段),则不应设定sequence,因为sequence是Oracle数据库...

    hibernate-annotations-3.4.0.GA.chm中文版

    11. **元数据注解**:@TableGenerator和@SequenceGenerator用于定义生成主键的元数据源。 通过深入学习这些注解及其用法,开发者能够熟练地在Hibernate中实现ORM,提高开发效率,减少与数据库交互的复杂度。同时,...

    Hibernate面试题专栏 - 最全的Hibernate面试题, Hibernate笔试题, Hibernate问题

    - 复合主键是自动生成的主键,通过@TableGenerator或@IdClass实现。 **8. 异常处理** - Hibernate提供了自己的异常体系,如HibernateException、ObjectRetrievalFailureException等,需要在编程中适当地捕获和处理...

    JPA标签(注解)详细说明

    - `@SequenceGenerator` 和 `@TableGenerator`:定义生成主键的序列或表。 4. **直接映射**: - `@Basic`:默认的属性映射,用于简单类型如int, String等。 - `@Enumerated`:用于枚举类型的映射。 - `@...

    hibernate属性级别注解实例代码

    - `GenerationType.TABLE` - 使用特定的数据库表来生成主键,配合`@TableGenerator`使用。 3. `@Column` - 这个注解将属性映射到数据库表的列,并可以覆盖默认的列定义。它包含一些可选属性,如`name`(列名)、`...

    hibernate-annotations-3.2.1.GA.zip

    5. @TableGenerator:非JPA标准,但提供了更灵活的主键生成策略。 四、实体生命周期管理 1. @PrePersist:在对象持久化前调用的方法。 2. @PostPersist:在对象成功持久化后调用的方法。 3. @PreUpdate:在对象...

Global site tag (gtag.js) - Google Analytics