【发布时间】:2019-07-01 13:54:13
【问题描述】:
我 300% 确定 id 字段是自动生成的,因为它在添加触发器之前非常有效。
我有一个实体,它使用自动生成的 id 字段扩展基本实体:
@MappedSuperclass
public abstract class BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
我已在 H2 中为该实体注册了触发器:
create trigger after_subtest_result_insert after insert on subtest_result
for each row call "package.path.SubtestResultTrigger";
触发器本身:
public class SubtestResultTrigger implements Trigger {
private static final int EQUIPMENT_ID = 5;
@Override
public void init(Connection conn, String schemaName, String triggerName,
String tableName, boolean before, int type) {
}
@Override
public void fire(Connection conn, Object[] oldRow, Object[] newRow)
throws SQLException {
try (PreparedStatement ps = conn.prepareStatement(
"update equipment e set " +
(...)
)
) {
ps.setObject(1, newRow[EQUIPMENT_ID]);
ps.setObject(2, newRow[EQUIPMENT_ID]);
ps.executeUpdate();
}
}
@Override
public void close() throws SQLException {
}
@Override
public void remove() throws SQLException {
}
}
当我取消注释 ps.executeUpdate(); 时,它会与 HibernateException: The database returned no natively generated identity value 断开。
H2 似乎在某个地方从执行的最后一个准备好的语句而不是第一个语句中获取生成的密钥,因为当触发器中的更新未运行时一切都很好。有什么解决方法或解决方法吗?
编辑:我意识到发生了什么,但我仍然对如何解决它一无所知。深入研究代码,H2 驱动程序有一个会话范围的 GeneratedKeys 对象,每次请求密钥时都会清除该对象,并且可能会在每次在同一会话中执行 PreparedStatement 时被覆盖。这使得实际上不可能有一个将任何内容写入数据库的后插入触发器。我将写一个错误报告,同时我将不得不要么不使用触发器(在这种情况下很难,我已经只诉诸触发器,因为每个替代方案都更糟)或者完全放弃 H2,我'我不确定我能不能,因为堆栈不在我的手中。
【问题讨论】:
标签: triggers h2 sql-insert