DB2序列的休眠和奇怪行为

时间:2010-02-11 08:20:21

标签: hibernate spring db2 sequence

我在Spring和DB2中使用Hibernate。我正在使用序列为实体生成主键。所有实体都使用相同的序列HIBERNATE_SEQUENCE,这是hibernate的默认值。

问题是最终成为主键的值比HIBERNATE_SEQUENCE返回的值高约10倍。

例如,在将新行插入tbl:

之后的这种情况
select max(id) as primary_key, nextval for hibernate_sequence sequence_value from tbl ;

primary_key sequence_value
501483661   50148373

我已经在所有实体的超类中映射了这样的主键:

@MappedSuperclass
public class AbstractEntity implements Serializable {
   @Id
   @GeneratedValue(strategy = GenerationType.SEQUENCE)
   private Integer id;

我希望hibernate使用从序列中获取的值,而不是序列值乘以10.执行此操作的正确方法是什么?

3 个答案:

答案 0 :(得分:2)

Hibernate似乎做了以下事情:

当hibernate需要主键时,它将从序列中获取值。 Hibernate将从单个序列值生成多个主键值。例如,hibernate将保留一个内部计数器,其值附加到序列值以获取主键值。当内部计数器达到其限制时,计数器复位,获得序列中的新值,并且主键过程重新开始。

例如:

  1. 从sequece获得的值是123.每个会话存储获得的序列值。
  2. 对于当前会话,生成的主键是1230,1231,1232,1233,...,1238,1239。计数器值连接到步骤1中获得的序列值。在需要时生成密钥。
  3. 现在主键生成过程全部开始。转到1。
  4. 这会产生以下影响:

    • 数据库序列值实际上乘以10
    • Hibernate不必为每个数据库插件读取数据库。上述算法将序列读取次数减少到10%(在单个会话中进行大量插入时)。
    • 每个其他非hibernate应用程序必须使用类似的算法从序列生成主键,否则在某些时候会出现主键冲突

    要使hibernate使用从序列中获取的实际值,可以使用此映射:

    @Id
    @GeneratedValue(generator="hibernate_sequence")
    @GenericGenerator(strategy="sequence", name="hibernate_sequence")
    private Integer id;
    

答案 1 :(得分:0)

DB2 create sequence命令上有一些可能会影响它的选项。 INCREMENT_BY表示每次调用nextval会增加多少值。带有NO_ORDER的CACHE保留一定数量的值,因此如果多个连接使用相同的序列,则可以更快地获取值,但代价是无序值。在深入研究Hibernate之前,我会检查序列是如何创建的。通过查看Hibernate代码,它非常简单 - 查看DB2Dialect,您可以看到它用于获取序列值的sql。

答案 2 :(得分:0)

我在allocationSize注释中解决了将@SequenceGenerator设置为1的问题。

示例:

@MappedSuperclass
public class AbstractEntity implements Serializable {
   @Id
   @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEQ_GENERATOR")
   private Integer id;

和实体:

@SequenceGenerator(name = "SEQ_GENERATOR", sequenceName = "MY_SEQUENCE", allocationSize = 1)
public class MyEntity extends AbstractEntity {