具有JPA 2序列生成的Postgresql中的奇怪id值

kos*_*ant 4 postgresql hibernate sequence jpa-2.0

该实体在id列上具有以下注释:

@Id
@SequenceGenerator(name = "JOB_MISFIRE_ID_GENERATOR", sequenceName="job_misfire_sequence", allocationSize=10)
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator = "JOB_MISFIRE_ID_GENERATOR")
@Column(unique = true, nullable = false)
private Long id;
Run Code Online (Sandbox Code Playgroud)

在数据库中,我有以下内容:

CREATE SEQUENCE job_misfire_sequence
  INCREMENT 10
  MINVALUE 1
  MAXVALUE 9223372036854775807
  START 1
  CACHE 1;
Run Code Online (Sandbox Code Playgroud)

序列用于获取列的默认值.

ALTER TABLE job_misfires
ALTER COLUMN id SET DEFAULT nextval('job_misfire_sequence');
Run Code Online (Sandbox Code Playgroud)

当我使用nextval('job_misfire_sequence')手动插入数据库时​​,一切正常.当序列的当前值为1时,生成以下id值:

 SELECT nextval('job_misfire_sequence'); --> 1
 SELECT nextval('job_misfire_sequence'); --> 11
 SELECT nextval('job_misfire_sequence'); --> 21
 SELECT nextval('job_misfire_sequence'); --> 31
Run Code Online (Sandbox Code Playgroud)

但是当hibernate在这个表中插入一行时会发生什么呢?它从这个序列得到了下一个值(在这个场景中是41)并将它乘以10并将其用作id值.这意味着插入的行现在具有id值410.

我究竟做错了什么?这种情况会导致冲突,因为hibernate没有使用序列提供的值.如果我已经理解了correclty
,那么注释中的allocationSize = 10和序列中的INCREMENT 10 的组合应该保证hibernate只需要从序列中每十个值请求一个新值.为什么这不会发生?为什么序列中的值乘以10?

我正在使用

  • Postgresql 9.0.3
  • Hibernate 3.5.5
  • Hibernate JPA 2.0 api 1.0.0 final

更新1:

正如互联网周围所建议的那样,在注释中将allocationSize值设置为1可以解决此问题.现在id值实际上取自db中的序列,我可以安全地在该表中手动插入行.

但:

  • allocateSize = 1会导致性能问题吗?
  • 是不是一个巨大的错误,序列中的值不是在休眠中使用,而是乘以allocationSize值?
  • 谁应该受到责备?休眠?
  • 有可用的修复方法吗?

kos*_*ant 7

看来这样做的正确方法如下:

@Id
@SequenceGenerator(name = "JOB_MISFIRE_ID_GENERATOR", sequenceName="job_misfire_sequence", allocationSize=1)
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator = "JOB_MISFIRE_ID_GENERATOR")
@Column(unique = true, nullable = false)
private Long id;
Run Code Online (Sandbox Code Playgroud)

在数据库中,我有以下内容:

CREATE SEQUENCE job_misfire_sequence
  INCREMENT 1
  MINVALUE 1
  MAXVALUE 9223372036854775807
  START 1
  CACHE 10;
Run Code Online (Sandbox Code Playgroud)

现在,当我使用nextval('job_misfire_sequence')手动插入数据库时​​,一切都按预期工作.当序列的当前值为1时,生成以下id值:

 SELECT nextval('job_misfire_sequence'); --> 1
 SELECT nextval('job_misfire_sequence'); --> 2
 SELECT nextval('job_misfire_sequence'); --> 3
 SELECT nextval('job_misfire_sequence'); --> 4
Run Code Online (Sandbox Code Playgroud)

现在,hibernate也可以按照我的预期运行.在我在一个会话中插入这4行后插入一行时,返回到hibernate的序列值为11. Hibernate使用它作为第一条记录的id值,11作为下一条记录的id值,依此类推.因为我在db中将CACHE设置设置为10,所以hibernate现在只需要调用一次序列,然后可以使用10个连续的id值.我确认情况确实如此,并且id值不重叠.

所以,关键点是:

  • 您必须在注释中使用allocationSize = 1

如果要优化db插入的性能,请使用

  • 在db中使用CACHE设置,其值大于1,但不要触及allocationSize

获得不错的顺序id值

  • 您必须使用INCREMENT 1


归档时间:

查看次数:

7707 次

最近记录:

14 年,6 月 前