Java JPA/Ebean-强制@Id严格递增+;1使用PostgreSQL

Java JPA/Ebean-强制@Id严格递增+;1使用PostgreSQL,java,postgresql,jpa,ebean,Java,Postgresql,Jpa,Ebean,我有以下型号: public class Parameter extends Model { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) public long id; } save()创建的记录如下所示: play=> select id from parameter; id ---- 1 2 3 4 5 21 (6 rows) 有没有一种方法可以告诉JPA总是将id增

我有以下型号:

public class Parameter extends Model {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    public long id;
}
save()
创建的记录如下所示:

play=> select id from parameter;
 id
----
  1
  2
  3
  4
  5
 21
(6 rows)

有没有一种方法可以告诉JPA总是将
id
增加一个整数,而不是随机跳到21?

您应该能够通过使用
@TableGenerator
allocationSize=1
来实现这一点。示例代码如下所示。您需要创建一个单独的表来存储主键、额外的工作,但比
@GeneratedValue
更便于携带

@TableGenerator(name="MAIN_PK_GEN", table="pk_gen", pkColumnName="GEN_NAME", valueColumnName="GEN_VALUE", pkColumnValue="MAIN_PK_GEN", allocationSize=1)
    @Id @GeneratedValue(strategy=GenerationType.TABLE, generator="MAIN_PK_GEN" )
    @Basic(optional = false)
    @Column(name = "PK")
    private Integer pk;
(但是使用
allocationSize=1
可能没有效率)

请参阅以获取逐步解释。

您所观察到的(跳到21)可能是4.0.5之前的Ebean的实现细节。Ebean正在序列上使用“提前提取”机制。在4.0.5版本之后,默认情况下,Eben切换到使用Postgres序列(因此,默认情况下,Eben/Postgres在4.0.5版本之后不会出现这种情况)。参考:


所有这些-‘精确递增1’通常是您希望避免的,因为它会成为并发问题(避免使autoincrement ID成为事务性的,因为这会引入争用)。当您需要“精确递增一”语义(如支票号码等)时,您可以提前批量创建。

如果您使用的是Oracle,请不要忘记添加allocationSize为1的SequenceGenerator:

    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "mysequence")
    @SequenceGenerator(name = "mysequence", sequenceName = "mysequence", allocationSize = 1)
    private Long id;

简言之,没有办法做到这一点。Id字段只保证是唯一的。有没有办法确保所有Id都比以前的Id大?那也可以。@doque在Ebean方面,它使用的是底层的DB序列(或DB autoincrement,取决于DB),因此通常是的,您会发现分配的ID比以前的任何ID都大,但严格来说不一定是这样,Oracle RAC也可能不是这样(或类似的聚集的DB,其中ID块是跨DB节点分配的)。您可以检查基础数据库上的DOCs /行为,但您可能认为添加“创建时”的时间戳列(使用Ebean时使用CreateTimestamp)更安全/更好。摘要:DB序列(和自动增量)将是唯一的,可能有间隙,通常是但不是严格递增的(取决于DB实现,例如Oracle RAC之类的DB集群),通常最好添加一个额外的“whenCreated”时间戳列,以帮助在您不能或不想依赖“IDs严格递增”时提供查询顺序。