Java 如何在spring DataSourceTransactionManager管理的每个事务中执行自定义sql代码?
考虑这样一种情况,我们有大量由Spring管理的java DAO类。这些bean中定义的每个方法都执行Spring数据源事务中的SQL代码,该事务由方法上的注释定义。现在我们需要在上述方法的目标执行之前运行一些自定义代码,这些代码必须在目标方法上的注释定义的同一事务中执行 基于R4J评论的更新: 我的DAO调用代理应该在DAO包中每个目标调用的事务中调用过程PR_Adm_Set_Usr:Java 如何在spring DataSourceTransactionManager管理的每个事务中执行自定义sql代码?,java,spring,spring-aop,spring-jdbc,Java,Spring,Spring Aop,Spring Jdbc,考虑这样一种情况,我们有大量由Spring管理的java DAO类。这些bean中定义的每个方法都执行Spring数据源事务中的SQL代码,该事务由方法上的注释定义。现在我们需要在上述方法的目标执行之前运行一些自定义代码,这些代码必须在目标方法上的注释定义的同一事务中执行 基于R4J评论的更新: 我的DAO调用代理应该在DAO包中每个目标调用的事务中调用过程PR_Adm_Set_Usr: @Aspect @Order(1000) @Component public class DaoProxy
@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()方法上的回滚。
不幸的是,直到我在我的上下文配置中将order添加到我的标记中,这才起作用
解决了这个问题。使用AOP应该是可行的,但棘手的部分是代理创建的顺序。如果您的方面组件将在管理事务的Spring代理之前被调用,那么您的自定义代码将在该事务之外被调用——这是您应该注意的一件事。除此之外,它应该是完全可行的。为了给您提供任何示例,我们需要查看您的代码示例,并对您尝试执行的操作进行更详细的解释。您不能使用Hibernate拦截器吗。您可以在执行前、执行后传递自定义查询。另外,由于您在同一事务中的拦截器中已经有sessionFactory,您也可以(确认这一点)获得回滚机制。使用aspect听起来也不错,但如果您希望它用于多个类,那么我相信Hibernate拦截器更有效…:-)@WeareBorg:在这个项目中没有hibernate可用,只有spring jdbc功能。@R4J:我提供了一些有问题的POC代码示例,您能指出提供的解决方案中的错误吗?问题解决了,我更改了