首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用JPA 2序列生成Postgresql中奇怪的id值

用JPA 2序列生成Postgresql中奇怪的id值
EN

Stack Overflow用户
提问于 2011-06-15 15:37:06
回答 4查看 8.4K关注 0票数 5

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

代码语言:javascript
复制
@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;

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

代码语言:javascript
复制
CREATE SEQUENCE job_misfire_sequence
  INCREMENT 10
  MINVALUE 1
  MAXVALUE 9223372036854775807
  START 1
  CACHE 1;

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

代码语言:javascript
复制
ALTER TABLE job_misfires
ALTER COLUMN id SET DEFAULT nextval('job_misfire_sequence');

当我使用nextval('job_misfire_sequence')手工插入数据库时,一切都很好。当序列的当前值为1时,将生成以下id值:

代码语言:javascript
复制
 SELECT nextval('job_misfire_sequence'); --> 1
 SELECT nextval('job_misfire_sequence'); --> 11
 SELECT nextval('job_misfire_sequence'); --> 21
 SELECT nextval('job_misfire_sequence'); --> 31

但是,当hibernate向这个表插入一行时,它会从这个序列获得下一个值(在此场景中为41 ),并将其乘以10,并使用该值作为id值。这意味着插入的行现在具有id值410。

我做错了什么?这种情况将导致冲突,因为hibernate不使用序列提供的值。如果我已经理解了

代码语言:javascript
复制
 allocationSize=10  in the annotation and      INCREMENT 10 in the sequence should quarantee that hibernate only has to ask for a new value from the sequence every tenth value. Why is this not happening? Why is the value from the sequence multiplied by 10?

我在用

3.5.5

  • Hibernate
  • Postgresql 9.0.3
  • Hibernate JPA2.0API1.0.0最终

更新1:

正如围绕internets的建议,在注释中将allocationSize值设置为1可以解决这个问题。现在,id值实际上是从db中的序列中提取的,我可以安全地在该表中手动插入行。

但是:

  • 会导致性能问题吗?
  • 不是像hibernate那样使用来自序列的值,而是乘以allocationSize值吗?
  • 是谁的错?Hibernate?
  • 有可用的修补程序吗?
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-06-15 16:13:30

这样做的正确方法似乎如下:

代码语言:javascript
复制
@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;

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

代码语言:javascript
复制
CREATE SEQUENCE job_misfire_sequence
  INCREMENT 1
  MINVALUE 1
  MAXVALUE 9223372036854775807
  START 1
  CACHE 10;

现在,当我使用nextval('job_misfire_sequence')手动插入到db时,一切都如愿以偿。当序列的当前值为1时,将生成以下id值:

代码语言:javascript
复制
 SELECT nextval('job_misfire_sequence'); --> 1
 SELECT nextval('job_misfire_sequence'); --> 2
 SELECT nextval('job_misfire_sequence'); --> 3
 SELECT nextval('job_misfire_sequence'); --> 4

现在hibernate也能像我期望的那样工作。当我在一次会话中插入这4行之后,当它插入一行时,返回给hibernate的序列值是11。Hibernate使用这个值作为第一条记录的id值,对下一条记录使用11,以此类推。因为我在db中将缓存设置设置为10,所以hibernate现在只需要调用一次序列,然后可以使用10个顺序id值。我确认了这一点,并且id值不重叠。

因此,要点是:

  • 您必须在注释

中使用allocationSize=1

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

allocationSize

  • 在db中使用值大于1的缓存设置,但不要触及该

获得良好的顺序id值

  • 您必须使用增量1
票数 7
EN

Stack Overflow用户

发布于 2011-06-15 15:44:49

按照我的理解,nextVal('job_misfire_sequence');将返回下一个序列值,从而返回您需要的值。Hibernate可以从中抽象出来,并假设从DB返回的值是正确的。因此,您不需要allocationSize=10,因为数据库已经返回了正确的值。

票数 0
EN

Stack Overflow用户

发布于 2011-06-15 15:51:15

我不知道Hibernate,但是当用PostgreSQL中的缓存值创建序列时,缓存是根据每个连接来操作的。这意味着,如果您从不同的会话(= connections)调用nextval(),您可能也会看到这种行为。

引用手册中的话:

如果对将由多个会话并发使用的序列对象使用大于一个缓存设置,则可能会获得

意外结果。每个会话将在访问序列对象期间分配和缓存连续的序列值,并相应地增加序列对象的last_value。然后,在该会话中使用nextval的下一个缓存-1只返回预先分配的值,而不触及序列对象。因此,当会话结束时,任何分配但未在会话中使用的数字都将丢失,从而导致序列中的“漏洞”。

确保您阅读了手册中的“备注”部分:http://www.postgresql.org/docs/current/static/sql-createsequence.html

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6360357

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档