I am 300% sure the id
field is autogenerated just fine, as this was perfectly working before adding the trigger.
I have an entity which extends a base entity with an autogenerated id field:
@MappedSuperclass
public abstract class BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
I have registered a trigger for that entity in H2:
create trigger after_subtest_result_insert after insert on subtest_result
for each row call "package.path.SubtestResultTrigger";
The trigger itself:
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 {
}
}
When I uncomment ps.executeUpdate();
, it breaks with HibernateException: The database returned no natively generated identity value
.
It seems like somewhere under the hood H2 gets the generated keys from the last prepared statement that was executed, rather than the first one, since everything is fine when the update in the trigger is not run. Is there any fix or workaround for this?
EDIT: I realize what's happening, I still have zero idea how to work around it. Digging into the code, the H2 driver has a session-wide GeneratedKeys
object, that is cleared every time the keys are requested, and presumably overwritten every time a PreparedStatement
is executed in the same session. This makes it literally impossible to have a post insert trigger that writes anything at all to the database. I'll write a bug report, in the meantime I'll have to either not use triggers (hard in this context, I'm already only resorting to triggers because every alternative is even worse) or just ditch H2 entirely, which I'm not sure I can since the stack is out of my hands.