java H2触发器在无限循环中运行

nkkqxpd9  于 9个月前  发布在  Java
关注(0)|答案(2)|浏览(73)

我为H2数据库创建了一个触发器来自动更新一个时间戳列“updated_ts”。当UPDATE sql语句被调用时,该触发器表现为一个无限循环。

UPATE main.doc doc SET 
value = 100.
WHERE doc.id = 1;

字符串

触发无限循环

@Override
    public void fire(Connection conn, Object[] oldRow, Object[] newRow) throws SQLException {
        
        log.debug("🔥🔥 FIRED Trigger for UpdateTimestamp table {}",
                this.schemaName.concat(".").concat(this.tableName));
        
        if(Objects.isNull(newRow))
            return;
        
        final Long id = (Long)newRow[0];

        log.debug("🔥🔥 FIRED Trigger for id {}", id);
        
        final LocalDate localDate = LocalDate.now();
        final LocalDateTime dateTime = LocalDateTime
                .of(localDate.getDayOfYear(), localDate.getMonth(), localDate.getDayOfMonth(), 0, 0, 0);
    
        final String update = new StringBuilder("UPDATE ")
                .append(this.schemaName).append(".")
                .append(this.tableName).append(" doc SET ")
                .append(" update_ts = ? ")
                .append(" where doc.id = ? ")
                .toString();
        
        final PreparedStatement statement = conn.prepareStatement(update);

        statement.setTimestamp(1, Timestamp.valueOf(dateTime));
        statement.setLong(2, id);
        
        final boolean ok = statement.execute();
        
        log.debug("Update status {} for UpdateTimestampShippingcalcDoc id {} table {}",
                ok , id, this.schemaName.concat(".").concat(this.tableName));
    }


我认为这是H2的

rqqzpn5f

rqqzpn5f1#

难怪会出现无限循环:每次在表中执行写操作时,H2都会调用触发器处理程序。因此,如果代码在方法中执行UPDATE,它将不断触发相同的处理程序。
不要在你的处理程序代码中包含数据:根据触发器规范,你可以修改行值(在写入行值之前),只要修改newRow单元格即可。

j9per5c4

j9per5c42#

这里不需要使用触发器,H2有非标准的MySQL风格的ON UPDATE子句,可以使用它来代替:

CREATE TABLE MAIN.DOC(
...
UPDATE_TS DATE
    DEFAULT CURRENT_DATE
    ON UPDATE CURRENT_DATE
    DEFAULT ON NULL
    NOT NULL,
...
);

字符串
DEFAULT表达式用于插入新行且未提供此列的值时,ON UPDATE表达式用于更新行且未提供此列的新值时,DEFAULT ON NULL将传递的空值转换为默认值。
如果你真的需要使用触发器(例如,由于您的应用程序试图设置自己的UPDATE_TS列的错误值,并且由于某种原因无法避免),该触发器必须只在newRow数组中设置值。但是不要在触发器中混淆遗留的datetime API,在H2的现代版本中,它们使用JSR-310数据类型。对于DATE列,使用newRow[/*0-based-column-index*/] = LocalDate.now()

相关问题