Hibernate,@ SequenceGenerator和allocationSize

G. *_*cki 109 java hibernate jpa hilo

我们都知道Hibernate在使用时的默认行为@SequenceGenerator- 它将实际数据库序列增加1,将此值乘以50(默认allocationSize值) - 然后将此值用作实体ID.

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

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

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

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

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

编辑:说
清楚.如果最后插入的记录具有ID = 1,则HB同时使用51, 52, 53...其新实体BUT的值:数据库中的序列值将设置为2.当其他应用程序使用该序列时,这很容易导致错误.

另一方面:规范说(根据我的理解)数据库序列应该被设置为51,同时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;
}
Run Code Online (Sandbox Code Playgroud)

persistence.xml中

<persistence-unit name="testPU">
  <properties>
    <property name="hibernate.id.new_generator_mappings" value="true" />
  </properties>
</persistence-unit>
Run Code Online (Sandbox Code Playgroud)

Ste*_*ole 39

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

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

  • 你怎么了?我是Hibernate的首席开发人员.我已经编写/共同编写了许多Hibernate类;) (20认同)
  • 我还注意到你是`org.hibernate.id.enhanced.SequenceStyleGenerator`的合着者.你让我很惊讶 (4认同)

Ami*_*nde 15

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

下一代Sequence Id基于allocationSize.

通过defualt它保持50太多.它也只会帮助你50在一个会话中接近记录,这些记录不会持久存在,并且将使用此特定会话和转换保留.

所以你应该在使用allocationSize=1时使用SequenceGenerator.对于大多数底层数据库,序列总是递增1.

  • 与性能无关?你真的**确定吗?我被教导用`allocationSize = 1` Hibernate对每个`save`操作都需要去数据库,以获得新的ID值. (10认同)
  • 这是一个微优化,在获取查询之前,Hibernate尝试在`allocationSize`范围内分配值,因此尝试避免查询数据库的序列。但是,如果将查询设置为1,则每次都会执行此查询。这几乎没有什么区别,因为如果您的数据库被其他应用程序访问,那么如果另一个应用程序同时使用相同的ID,它将产生问题。 (2认同)
  • 好.一切都是应用程序特定的,不是吗!如果您的应用程序是只读应用程序,那么使用分配大小1000或1的影响绝对为0.另一方面,这些是最佳实践.如果你不尊重他们收集的最佳实践,那么综合影响就会使你的申请变得迟钝.另一个例子是当你绝对不需要时就开始一个交易. (2认同)