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

Java 审计列@PrePersist和@PreUpdate的Spring JdbcTemplate实现,java,spring,oracle,jpa,jdbctemplate,Java,Spring,Oracle,Jpa,Jdbctemplate,如果我使用Hibernate/JPA,我会在每次更新/插入之前(或之后)使用@PrePersist和@PreUpdate(或@PostPersist和@PostUpdate)将数据放入审计列。但是,仅使用Spring JdbcTemplate,实现这一点的最佳方法是什么?据我所知,JdbcTemplate没有附加任何生命周期机制(这实际上是有意义的,因为该类只是简化Jdbc工作流的实用工具) 如果您使用JdbcTemplate,则必须手动执行审核操作使用AOP并向保存或更新数据的方法添加@Bef

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

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


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

使用AOP并向保存或更新数据的方法添加@Before建议。

谢谢您的建议。具体来说,对于Oracle,我能够通过从表示受影响行的初始插入(使用Spring的KeyHolder)或初始更新(使用Oracle的returning INTO子句)返回一个键来实现这一点,然后执行后续查询以更新审计列。代码位于抽象的基本DAO中,该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);
    }
}
@Inject
私有名称参数jdbc模板名称djdbc;
公共长插入(字符串sql、映射参数、字符串表、字符串键列){
SqlParameterSource paramSource=新映射SqlParameterSource(params);
KeyHolder KeyHolder=新生成的KeyHolder();
int numberOfAffectedRows=namedJdbc.update(sql,paramSource,keyHolder,新字符串[]{keyColumn});
Long key=(numberOfAffectedRows==1)?keyHolder.getKey().longValue():-1L;
如果(键!=-1){
updateAuditColumns(表,键列,key.toString(),true);
}
返回键;
}
公共void插入(字符串sql、映射参数、字符串表){
SqlParameterSource paramSource=新映射SqlParameterSource(params);
KeyHolder KeyHolder=新生成的KeyHolder();
int numberOfAffectedRows=namedJdbc.update(sql,paramSource,keyHolder);
ROWID ROWID=(numberOfAffectedRows==1)?(ROWID)keyHolder.getKeys().get(“ROWID”):null;
if(rowId!=null){
UpdateAudiColumns(表“ROWID”,ROWID.stringValue(),true);
}
}
公共无效更新(字符串sql、映射参数、字符串表){
sql+=“将ROWID返回到?”;//特定于Oracle
最终字符串finalSql=sql;
最终映射finalParams=参数;
String rowId=namedJdbc.getjdbcooperations().execute(新的PreparedStatementCreator()){
@凌驾
公共PreparedStatement createPreparedStatement(连接con)引发SQLException{
OraclePreparedStatement stmt=(OraclePreparedStatement)con.prepareStatement(finalSql);
for(Map.Entry:finalParams.entrySet()){
stmt.setObjectAtName(entry.getKey(),entry.getValue());//jdbc驱动程序将选择类型
}
stmt.registerReturnParameter(finalParams.entrySet().size()+1,OracleTypes.VARCHAR);
返回stmt;
}
},新的PreparedStatementCallback(){
@凌驾
公共字符串doInPreparedStatement(PreparedStatement s)引发SQLException、DataAccessException{
OraclePreparedStatement stmt=(OraclePreparedStatement)s;
stmt.executeUpdate();
ResultSet rs=stmt.getReturnResultSet();
试一试{
如果(rs.next()){
返回rs.getString(1);
}
抛出新的IllegalStateException(“ROWID未返回”);
}最后{
rs.close();
}
}
});
if(rowId!=null){
updateAuditColumns(表“ROWID”,ROWID,false);
}
}