休眠、@SequenceGenerator和分配大小

2022-08-31 08:04:21

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

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

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

需要明确的是:我不关心生成的ID之间的差距。

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

是否有人知道此问题的任何解决方案(无需设置,从而降低性能)?allocationSize=1

编辑:
让事情变得清晰。如果上次插入的记录 ID = ,则 HB 同时为其新实体使用值,但同时:序列在数据库中的值将设置为 。当其他应用程序使用该序列时,这很容易导致错误。151, 52, 53...2

在另外一方面:规范说(在我的理解中)数据库序列应该设置为,同时HB应该使用范围中的值。512, 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;
}

持久性.xml

<persistence-unit name="testPU">
  <properties>
    <property name="hibernate.id.new_generator_mappings" value="true" />
  </properties>
</persistence-unit>

答案 1

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

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


答案 2

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

下一代序列 ID 基于分配大小。

通过devalut,它被保留为太多了。这也只有在您将在一个会话中拥有几乎关于记录的记录时才会有所帮助,这些记录不会持久化,并且将使用此特定会话和事务进行持久化。5050

因此,您应该在使用 时始终使用。对于大多数基础数据库,序列总是递增 。allocationSize=1SequenceGenerator1


推荐