考虑我们有大量由Spring管理的Java DAO类的情况。这些bean中定义的每个方法都在Spring的数据源事务中执行SQL代码,该事务由方法的注释定义。现在我们需要在目标执行所提到的方法之前运行一些自定义代码,这个代码必须在目标方法的注释定义的同一事务中执行。
根据R4J评论更新:
我的DAO调用代理应该在DAO包中的每个目标调用的事务中调用过程PR_Adm_Set_Usr:
@Aspect
@Order(1000)
@Component
public class DaoProxy {
private static final Logger logger = LoggerFactory.getLogger(DaoProxy.class);
@Autowired
private ContextDAO contextDAO;
@Autowired
private DataSourceTransactionManager txManager;
@Before("execution(* xx.yy.dao.*.*(..)) xx.yy.core.dao.*.*(..))")
@Transactional(propagation = Propagation.SUPPORTS)
public void setContext() throws Throwable {
JdbcTemplate jdbc = new JdbcTemplate(txManager.getDataSource());
if(SecurityContextHolder.getContext()!=null &&
SecurityContextHolder.getContext().getAuthentication()!=null &&
SecurityContextHolder.getContext().getAuthentication().getPrincipal()!=null){
SimpleJdbcCall jdbcCall = new SimpleJdbcCall(jdbc)
.withProcedureName("PR_Adm_Set_Usr")
.withoutProcedureColumnMetaDataAccess().declareParameters(
new SqlParameter("user", OracleTypes.VARCHAR));
jdbcCall.setAccessCallParameterMetaData(false);
MapSqlParameterSource params = new MapSqlParameterSource()
.addValue("user", SecurityContextHolder.getContext().getAuthentication().getName() );
jdbcCall.execute(params);
}else{
logger.warn("No context available!!!");
}
}
}
在SomeDAO类中调用DAO示例:
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public Object shiftDate(Long fileId, Long interval) {
String a=null;
a.toString();
JdbcTemplate jdbc = new JdbcTemplate(txManager.getDataSource());
SimpleJdbcCall jdbcCall = new SimpleJdbcCall(jdbc)
.withCatalogName("somepackage")
.withProcedureName("someprocedure")
.withoutProcedureColumnMetaDataAccess()
.declareParameters(
new SqlParameter("p_file_id", OracleTypes.NUMBER),
new SqlParameter("p_interval", OracleTypes.NUMBER)
);
jdbcCall.setAccessCallParameterMetaData(false);
MapSqlParameterSource params = new MapSqlParameterSource()
.addValue("p_file_id", fileId)
.addValue("p_interval", interval);
jdbcCall.execute(params);
return null;
}
正如您所看到的,DAO调用中的前两行会导致NullPointerException,这会导致AOP setContext()方法的回滚。 不幸的是,在我的上下文配置中将订单添加到我的标签之前,这不起作用。
<tx:annotation-driven order="1"/>
解决了这个问题。