我尝试使用序列为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();
}
}
答案 0 :(得分:1)
感兴趣的人的临时解决方法:在ebean.properties中,设置
ebean.databaseSequenceBatchSize=1