使用Eclipselink生成JPA的旧序列值

时间:2016-06-20 07:36:47

标签: hibernate jpa eclipselink spring-data-jpa

当Eclipselink用作ORM时,生成的JPA实体的id会生成一个旧的",使用过的数字,但是对于Hibernate,id是序列的正确下一个值。 在实体类中,我使用带有id字段

的这些注释
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "s_customer")
@SequenceGenerator(name = "s_customer", sequenceName = "S_CUSTOMER")
private Long id;

我使用 flyway 来设置和填充db:

public void migrate(JdbcTemplate jdbcTemplate) throws Exception {
    jdbcTemplate.execute("create sequence S_CUSTOMER");
    jdbcTemplate.execute("create table CUSTOMER (" +
            "ID BIGINT PRIMARY KEY," +
            "DISPLAY_NAME VARCHAR(3000)," +
            "VERSION BIGINT" +
            ")");
}


public void migrate(JdbcTemplate jdbcTemplate) throws Exception {
    for (int i = 0; i < 10000; i++) {
        jdbcTemplate.update(
                "insert into CUSTOMER (ID, DISPLAY_NAME, VERSION) " + "select nextval('S_CUSTOMER'), ?, ? ",
                "SAP-SE", 0);
    }
}

作为数据库,我使用PostgreSQL。

当我的应用程序要使用eclipselink持久保存一个新实体时,我收到一个错误,因为该实体得到了一个&#34; old&#34; ID:

Call: INSERT INTO CUSTOMER (ID, DISPLAY_NAME, VERSION) VALUES (?, ?, ?)
bind => [3 parameters bound]
Query: InsertObjectQuery(Customer(id=9959, displayName=Bäckerei Brötchen, version=1)); nested exception is javax.persistence.RollbackException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.6.3.v20160428-59c81c5): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "customer_pkey"
Detail: Key (id)=(9959) already exists. 

但是当我手动选择序列的当前值时,我得到值&#34; 10004&#34;。那么为什么eclipselink会返回已经使用过的序列值呢? hibernate也是如此。

2 个答案:

答案 0 :(得分:0)

虽然这是一个老问题,但最近我遇到了同样的问题。

当你在数据库中创建序列时,allocationSize(默认为50)应与子句INCREMENT(默认为1)相同。 所以如果你想要一个它会递增的序列,让我们说100,你应该这样写:

CREATE SEQUENCE my_seq_id
  INCREMENT 100
  MINVALUE 1
  MAXVALUE 9223372036854775807
  START 1;

JPA实体应该是这样的:

@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "my_seq_id")
@SequenceGenerator(name = "my_seq_id", sequenceName = "my_seq_id", allocationSize = 100)
private Long id;

答案 1 :(得分:0)

我已经具有与数据库序列中定义的相同的allocationSize,但是仍然偶尔会得到旧的序列值。