审计列的@PrePersist和@PreUpdate的Spring JdbcTemplate实现

时间:2014-04-23 17:24:11

标签: java spring oracle jpa jdbctemplate

如果我使用Hibernate / JPA,我会使用@PrePersist和@PreUpdate(或@PostPersist和@PostUpdate)在每次更新/插入之前(或之后)将数据放入审核列。但是,仅使用Spring JdbcTemplate,实现此目的的最佳方法是什么?

3 个答案:

答案 0 :(得分:0)

据我所知,JdbcTemplate没有附加生命周期机制(这实际上是有意义的,因为该类只是一个简化Jdbc工作流的实用程序)。

如果您使用JdbcTemplate,则必须手动执行审核操作

答案 1 :(得分:0)

使用AOP并将@Before建议添加到持久化或更新数据的方法中。

答案 2 :(得分:0)

感谢您的想法。特别是对于Oracle,我能够通过从初始插入(使用Spring的KeyHolder)返回一个键或者使用表示受影响的行的初始更新(使用Oracle的RETURNING INTO子句),然后执行后续查询来更新审计列来实现这一点。 。代码位于抽象基础DAO中,由需要此功能的DAO子类化。

@Inject
private NamedParameterJdbcTemplate namedJdbc;

public Long insert(String sql, Map<String, Object> params, String table, String keyColumn) {
    SqlParameterSource paramSource = new MapSqlParameterSource(params);
    KeyHolder keyHolder = new GeneratedKeyHolder();
    int numberOfAffectedRows = namedJdbc.update(sql, paramSource, keyHolder, new String[]{keyColumn});
    Long key = (numberOfAffectedRows == 1) ? keyHolder.getKey().longValue() : -1L;
    if (key != -1) {
        updateAuditColumns(table, keyColumn, key.toString(), true);
    }
    return key;
}

public void insert(String sql, Map<String, Object> params, String table) {
    SqlParameterSource paramSource = new MapSqlParameterSource(params);
    KeyHolder keyHolder = new GeneratedKeyHolder();
    int numberOfAffectedRows = namedJdbc.update(sql, paramSource, keyHolder);
    ROWID rowId = (numberOfAffectedRows == 1) ? (ROWID) keyHolder.getKeys().get("ROWID") : null;
    if (rowId != null) {
        updateAuditColumns(table, "ROWID", rowId.stringValue(), true);
    }
}

public void update(String sql, Map<String, Object> params, String table) {
    sql += " returning ROWID into ?";//Oracle specific
    final String finalSql = sql;
    final Map<String, Object> finalParams = params;

    String rowId = namedJdbc.getJdbcOperations().execute(new PreparedStatementCreator() {
        @Override
        public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
            OraclePreparedStatement stmt = (OraclePreparedStatement) con.prepareStatement(finalSql);
            for (Map.Entry<String, Object> entry : finalParams.entrySet()) {
                stmt.setObjectAtName(entry.getKey(), entry.getValue());//jdbc driver will choose type
            }
            stmt.registerReturnParameter(finalParams.entrySet().size()+1, OracleTypes.VARCHAR);
            return stmt;
        }
    }, new PreparedStatementCallback<String>() {
        @Override
        public String doInPreparedStatement(PreparedStatement s) throws SQLException, DataAccessException {
            OraclePreparedStatement stmt = (OraclePreparedStatement) s;
            stmt.executeUpdate();
            ResultSet rs = stmt.getReturnResultSet();
            try {
                if (rs.next()) {
                    return rs.getString(1);
                }
                throw new IllegalStateException("ROWID not returned");
            } finally {
                rs.close();
            }
        }
    });

    if (rowId != null) {
        updateAuditColumns(table, "ROWID", rowId, false);
    }
}