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
我正在尝试使用序列为我在 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 我认为这是一个错误。
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