Ebean Annotations - 在 DB2 中使用序列生成 ID
Posted
技术标签:
【中文标题】Ebean Annotations - 在 DB2 中使用序列生成 ID【英文标题】:Ebean Annotations - Using sequences to generate IDs in DB2 【发布时间】:2016-05-18 19:19:01 【问题描述】:我正在尝试使用序列为我在 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 中的列(来自 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 序列的一个错误。此函数生成与 db2 一起使用时为我返回错误的 SQl
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();
【问题讨论】:
您的设置告诉 JPA 从序列中获取 ID 值并在插入中使用它。我猜这会干扰您的触发器,它也在设置 ID 值。为您的 JPA 提供程序打开日志记录并查看正在执行的语句以确定问题所在,但我认为您可能不应该在数据库中使用触发器。标识可能正在工作,因为它告诉 JPA 提供程序查找在插入语句执行后设置的序列值,这与您的触发器正在执行的操作相匹配。but when using ebean the statement fails
...您没有说错误是什么吗?当然,Ebean 并不期望触发因素存在。请注意,DB2 支持 Identity 和 Sequences ...所以假设您已经考虑过这一点。
Ebean 不是 JPA 的实现 - 它使用 JPA 注释。如果不是,我将删除它的提及。我现在已经包含了堆栈跟踪,但其他日志记录没有返回任何值得注意的东西。我希望对 OracleDB 和 DB2 使用相同的类,这就是我尝试在 DB2 中实现序列生成 ID 的原因
好的,清理干净了。删除触发器但保留序列和注释并不能解决问题,返回相同的错误。
是否有我可以在属性文件中设置的 ebean 属性列表?我在文档中找不到任何内容。
【参考方案1】:
感兴趣的人的临时解决方法:在 ebean.properties 中设置
ebean.databaseSequenceBatchSize=1
【讨论】:
以上是关于Ebean Annotations - 在 DB2 中使用序列生成 ID的主要内容,如果未能解决你的问题,请参考以下文章
Play Framework - Ebean - 没有为类“类名”注册 ScalarType
尝试将 Json 存储在 DB 中时,Ebean 'No service implementation found for SpiJsonService'