Ebean 注释 - 使用序列在 DB2 中生成 ID

Ebean Annotations - Using sequences to generate IDs in DB2

我正在尝试使用序列为我在 DB2 中的 table 生成增量 ID。当我将 SQL 语句直接发送到数据库时它有效,但是当使用 ebean 时该语句失败。这是 Java 中的字段:

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "TABLENAME_IDNAME_TRIG")
@SequenceGenerator(name = "TABLENAME_IDNAME_TRIG", sequenceName = "TABLENAME_IDNAME_SEQ")
@Column(name = "IDNAME")
private Long id;

这是 SQL 中的专栏(来自 TOAD):

Name            Data type   Not Null    Default Generated   Bit Data    Scope   Identity    
IDNAME          INTEGER     Yes                             No                  No

这里是 SQL 中的序列定义:

CREATE OR REPLACE SEQUENCE SCHEMA.TABLENAME_IDNAME_SEQ 
  AS INTEGER CACHE 50 ORDER;

触发器:

CREATE OR REPLACE TRIGGER SCHEMA.TABLENAME_IDNAME_TRIG
  NO CASCADE BEFORE INSERT
  ON TABLENAME
  REFERENCING 
    NEW AS OBJ
  FOR EACH ROW
BEGIN 
  SET obj.IDNAME=NEXT VALUE FOR SCHEMA.TABLENAME_IDNAME_SEQ;
END;

我这里的注释有什么问题?作为一个(重要的)旁注 - 当我将 GenerationType 设置为 AUTO、TABLE 或 IDENTITY 时,它可以工作,即使它不应该,因为我也使用这个对象来表示并行 oracle table 也使用序列生成 ID。

编辑以包含错误消息:

javax.persistence.PersistenceException: Error getting sequence nextval
...
Caused by: com.ibm.db2.jcc.am.SqlSyntaxErrorException: DB2 SQL Error: SQLCODE=-348, SQLSTATE=428F9, SQLERRMC=NEXTVAL FOR SCHEMA.TABLENAME_IDNAME_SEQ, DRIVER=4.19.49

编辑 2:失败的特定 Sql 语句是:

values nextval for QA_CONNECTION_ICONNECTIONI_SEQ union values nextval for QA_CONNECTION_ICONNECTIONI_SEQ union values nextval for QA_CONNECTION_ICONNECTIONI_SEQ

这是 SQL 由 Ebean 生成的。这是真实语句的缩小版本,重复了 20 次,所以我猜是在生成缓存查询时出了问题。

编辑 3:我认为这可能是 Ebean 使用 DB2 序列时的错误。当与 db2

一起使用时,此函数生成 SQl returns 对我来说是一个错误
public DB2SequenceIdGenerator(BackgroundExecutor be, DataSource ds, String seqName, int batchSize) {
  super(be, ds, seqName, batchSize);
  this.baseSql = "values nextval for " + seqName;
  this.unionBaseSql = " union " + baseSql;
}

编辑 4:基于此 SO link 我认为这是一个错误。 正确的 class 大概是这样的?虽然我从来没有尝试过构建这个库,所以我无法测试它。我想是时候学习如何打开缺陷了。

public class DB2SequenceIdGenerator extends SequenceIdGenerator {

  private final String baseSql;
  private final String unionBaseSql;
  private final String startSql;

  public DB2SequenceIdGenerator(BackgroundExecutor be, DataSource ds, String seqName, int batchSize) {
    super(be, ds, seqName, batchSize);
    this.startSql = "values "
    this.baseSql = "(nextval for " + seqName);
    this.unionBaseSql = ", " + baseSql;
  }

  public String getSql(int batchSize) {
    StringBuilder sb = new StringBuilder();
    sb.append(startSql);
    sb.append(baseSql);
    for (int i = 1; i < batchSize; i++) {
      sb.append(unionBaseSql);
    }

    return sb.toString();
  }
}

有兴趣者的临时解决方法:在 ebean.properties 中设置

ebean.databaseSequenceBatchSize=1