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

时间:2016-05-18 19:19:02

标签: db2 ebean

我尝试使用序列为DB2中的表生成递增的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(From 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表,也使用序列进行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

哪个是Ebean生成的SQL。这是真实语句的一个较小版本,重复了20次,因此在生成缓存查询时我猜错了。

编辑3:我认为这可能是Ebean使用DB2序列的一个错误。此函数生成SQl,当与db2

一起使用时,它会为我返回错误
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链接,我认为这是一个错误。 Can't insert multiple values into DB2 by using UNION ALL and generate IDs from sequence 正确的类可能看起来像这样?虽然我还没有尝试过建造图书馆,但我无法对其进行测试。是时候学习如何打开缺陷了。

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();
  }
}

1 个答案:

答案 0 :(得分:1)

感兴趣的人的临时解决方法:在ebean.properties中,设置

ebean.databaseSequenceBatchSize=1