Java 审计列@PrePersist和@PreUpdate的Spring JdbcTemplate实现
如果我使用Hibernate/JPA,我会在每次更新/插入之前(或之后)使用@PrePersist和@PreUpdate(或@PostPersist和@PostUpdate)将数据放入审计列。但是,仅使用Spring JdbcTemplate,实现这一点的最佳方法是什么?据我所知,JdbcTemplate没有附加任何生命周期机制(这实际上是有意义的,因为该类只是简化Jdbc工作流的实用工具)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
如果您使用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);
}
}