java - Hibernate,@ SequenceGenerator和allocationSiz

我们都知道使用hibernate.id.new_generator_mappings=true时Hibernate的默认行为 - 它将实际数据库序列增加1,将此值乘以50(默认值为2, 3 ... 50值) - 然后将此值用作实体ID。

这是不正确的行为,并与规范冲突说:

allocationSize - (可选)从序列中分配序列号时的增量。

要明确:我不打算生成ID之间的差距。

我关心的是与底层数据库序列不一致的ID。 例如:任何其他应用程序(例如使用普通JDBC)可能希望在从序列获取的ID下插入新行 - 但所有这些值可能已被Hibernate使用! 疯狂。

有人知道这个问题的任何解决方案(没有设置hibernate.id.new_generator_mappings=true,从而降低性能)?

编辑:
说清楚。如果最后插入的记录具有ID = hibernate.id.new_generator_mappings=true,则HB同时使用值2, 3 ... 50用于其新实体但是:数据库中的序列值将设置为2。当其他应用程序使用该值时,这很容易导致错误 序列。

另一方面:规范说(根据我的理解)数据库序列应设置为hibernate.id.new_generator_mappings=true,同时HB应使用范围2, 3 ... 50的值


更新:
正如Steve Ebersole在下面提到的那样:通过设置hibernate.id.new_generator_mappings=true可以启用我描述的行为(也是最直观的行为)。

谢谢大家。

更新2:
对于未来的读者,您可以在下面找到一个有效的例子。

@Entity
@Table(name = "users")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "USERS_SEQ")
    @SequenceGenerator(name = "USERS_SEQ", sequenceName = "SEQUENCE_USERS")
    private Long id;
}

persistence.xml中

<persistence-unit name="testPU">
  <properties>
    <property name="hibernate.id.new_generator_mappings" value="true" />
  </properties>
</persistence-unit>
G. Demecki asked 2019-08-13T06:51:20Z
5个解决方案
33 votes

要绝对清楚......你所描述的内容不会以任何方式与规范冲突。 该规范讨论了Hibernate为您的实体分配的值,而不是实际存储在数据库序列中的值。

但是,可以选择获取您正在寻找的行为。 首先看看我的回复是否有办法使用JPA注释和Hibernate动态选择@GeneratedValue策略? 这将为您提供基础知识。 只要您设置为使用SequenceStyleGenerator,Hibernate将使用&#34;池化优化器&#34;来解释allocationSize。 在SequenceStyleGenerator中。 &#34;汇集优化器&#34; 用于允许增加&#34;的数据库。 创建序列的选项(并非所有支持序列的数据库都支持增量)。 无论如何,请阅读那里的各种优化策略。

Steve Ebersole answered 2019-08-13T06:51:43Z
10 votes

allocationSize=1在获取查询之前,这是一个微优化Hibernate尝试在allocationSize的范围内分配值,因此尽量避免查询数据库的序列。 但是如果将其设置为1,则每次都会执行此查询。这几乎没有任何区别,因为如果您的数据库被其他应用程序访问,那么如果另一个应用程序同时使用相同的ID,则会产生问题。

下一代Sequence Id基于allocationSize。

通过defualt它保持为allocationSize=1太多了。 只有在一个会话中有大约SequenceGenerator个记录且没有持久存在并且将使用此特定会话和转换保留的记录时,它也将只有帮助。

因此,在使用SequenceGenerator时应始终使用allocationSize=1。对于大多数基础数据库,序列始终增加1

Amit Deshpande answered 2019-08-13T06:52:32Z
1 votes

Steve Ebersole&amp; 其他成员,
你能否解释一个有更大差距的id的原因(默认为50)?我正在使用Hibernate 4.2.15并在org.hibernate.id.enhanced.OptimizerFactory cass中找到以下代码。

if ( lo > maxLo ) {
   lastSourceValue = callback.getNextValue();
   lo = lastSourceValue.eq( 0 ) ? 1 : 0;
   hi = lastSourceValue.copy().multiplyBy( maxLo+1 ); 
}  
value = hi.copy().add( lo++ );

每当它到达if语句的内部时,hi值变得越来越大。 因此,在频繁重启服务器的测试过程中,我的id会生成以下序列ID:
1,2,3,4,19,250,251,252,400,550,750,751,752,850,1100,1150。

我知道你已经说它与规范没有冲突,但我相信这对大多数开发者来说都是非常意外的情况。

任何人的输入都会很有帮助。

Jihwan

更新:ne1410s:感谢您的编辑。
克里克:好的。 我去做。 这是我在这里的第一篇文章,并不确定如何使用它。

现在,我更好地理解为什么maxLo用于两个目的:由于hibernate一次调用DB序列,继续增加Java级别的id,并将其保存到DB,Java级别id值应该考虑在没有调用的情况下改变了多少 下次调用序列时的DB序列。

例如,序列id在某一点为1,而休眠则为5,6,7,8,9(其中allocationSize = 5)。 下次,当我们得到下一个序列号时,DB返回2,但是hibernate需要使用10,11,12 ...所以,这就是为什么&#34; hi = lastSourceValue.copy()。multiplyBy(maxLo + 1))&#34; 用于从DB序列返回的2中获取下一个id 10。 在频繁的服务器重启期间似乎只是困扰的事情,这是我的问题与更大的差距。

因此,当我们使用SEQUENCE OF时,表中插入的id与DB中的SEQUENCE编号不匹配。

Jihwan answered 2019-08-13T06:54:20Z
1 votes

在深入研究hibernate源代码之后下面的配置在50次插入后转到Oracle db以获取下一个值。 因此,每次调用时,使INST_PK_SEQ增量为50。

Hibernate 5用于以下策略

请查看下面[http://docs.jboss.org/hibernate/orm/5.1/userguide/html_single/Hibernate_User_Guide.html#identifiers-generators-sequence]

@Id
@Column(name = "ID")
@GenericGenerator(name = "INST_PK_SEQ", 
strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator",
parameters = {
        @org.hibernate.annotations.Parameter(
                name = "optimizer", value = "pooled-lo"),
        @org.hibernate.annotations.Parameter(
                name = "initial_value", value = "1"),
        @org.hibernate.annotations.Parameter(
                name = "increment_size", value = "50"),
        @org.hibernate.annotations.Parameter(
                name = SequenceStyleGenerator.SEQUENCE_PARAM, value = "INST_PK_SEQ"),
    }
)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "INST_PK_SEQ")
private Long id;
fatih tekin answered 2019-08-13T06:55:03Z
0 votes

我会检查DDL中的模式中的序列。 JPA实现仅负责创建具有正确分配大小的序列。 因此,如果分配大小为50,那么您的序列在其DDL中必须具有50的增量。

这种情况通常可以通过创建具有分配大小1的序列然后配置为分配大小50(或默认值)但序列DDL未更新而发生。

Hasan Ceylan answered 2019-08-13T06:55:37Z
translate from https://stackoverflow.com:/questions/12745751/hibernate-sequencegenerator-and-allocationsize