使用JPA 2序列生成的Postgresql中的怪异id值

| 该实体在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;
在数据库中,我具有以下内容:
CREATE SEQUENCE job_misfire_sequence
  INCREMENT 10
  MINVALUE 1
  MAXVALUE 9223372036854775807
  START 1
  CACHE 1;
然后使用该序列获取列的默认值。
ALTER TABLE job_misfires
ALTER COLUMN id SET DEFAULT nextval(\'job_misfire_sequence\');
当我使用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
但是,当hibernate在该表中插入一行时,会发生的事情是它从该序列中获取下一个值(在本方案中为41)并将其乘以10并将其用作id值。这意味着插入的行现在具有id值410。 我究竟做错了什么?由于休眠状态未使用序列提供的值,因此这种情况将导致冲突。如果我了解正确性,     distributionSize = 10 在注释中     增加10 在序列中应该隔离,休眠只需要每十分之一的值从序列中请求一个新值。为什么这没有发生?为什么序列中的值乘以10? 我在用着 PostgreSQL 9.0.3 休眠3.5.5 Hibernate JPA 2.0 API 1.0.0最终版 更新1: 如互联网上所建议的那样,在批注中将allocationSize值设置为1可解决此问题。现在,id值实际上是从db中的序列中获取的,我可以安全地在该表中手动插入行。 但: 分配大小= 1是否会导致性能问题? 序列中的值不像冬眠中那样使用而是乘以allocationSize值,这不是一个巨大的错误吗? 谁该怪?冬眠? 有可用的修复程序吗?     
已邀请:
        看来执行此操作的正确方法如下:
@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;
在数据库中,我具有以下内容:
CREATE SEQUENCE job_misfire_sequence
  INCREMENT 1
  MINVALUE 1
  MAXVALUE 9223372036854775807
  START 1
  CACHE 10;
现在,当我使用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
现在,休眠也可以按我期望的方式工作。当我在一个会话中插入这4行之后插入一行时,返回给hibernate的序列值为11。Hibernate将其用作第一条记录的id值,将11用作下一条记录的ID值,依此类推。因为我在数据库中将CACHE设置设置为10,所以休眠现在只需要调用一次序列,然后可以使用10个连续的id值。我确认确实是这样,并且id值不重叠。 因此,关键点是: 您必须在注释中使用allocationSize = 1 如果要优化数据库插入的性能,请使用 在db中使用CACHE设置,其值大于1,但请勿触摸 获得良好的顺序ID值 您必须使用INCREMENT 1     
        按照我的理解,ѭ7将返回下一个SEQUENCE值,即您需要的值。 Hibernate可以对此进行抽象,并假定从DB返回的值是正确的。因此,您不需要
allocationSize=10
,因为数据库已经返回正确的值。     
        我不知道Hibernate,但是当在PostgreSQL中使用缓存值创建序列时,缓存将基于每个连接进行操作。这意味着,如果您从不同的会话(=连接)中调用nextval(),您可能也会看到此行为。 引用手册:   可能会得到意外的结果   如果缓存设置大于1是   用于序列对象   被多个同时使用   会议。每个会话将分配   并缓存连续的序列值   在一次访问序列时   反对并增加顺序   对象的last_value。然后,   nextval的下一个cache-1使用   在该会话中,只需返回   预先分配的值,请勿触摸   序列对象。所以,任何数字   已分配但未在   该会话将丢失   结束,导致“孔”   顺序 确保您阅读了手册中的“注释”部分: http://www.postgresql.org/docs/current/static/sql-createsequence.html     
这就是它的工作方式。 当使用带有
allocationSize
的序列生成器时,Hibernate从序列中获得一个数字以生成
allocationSize
标识符。因此,在从序列中获得值
N
之后,它会生成从
allocationSize * N
allocationSize * (N + 1) - 1
的标识符。然后,它从序列中获取下一个值,以生成下一组标识符。如果下一个值是
N + 1
,则生成的标识符是连续的,因此它期望产生序列号的序列号。 因此,无需在序列定义中指定“ 15”。     

要回复问题请先登录注册