Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/393.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在spring DataSourceTransactionManager管理的每个事务中执行自定义sql代码?_Java_Spring_Spring Aop_Spring Jdbc - Fatal编程技术网

Java 如何在spring DataSourceTransactionManager管理的每个事务中执行自定义sql代码?

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

考虑这样一种情况,我们有大量由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()方法上的回滚。 不幸的是,直到我在我的上下文配置中将order添加到我的标记中,这才起作用


解决了这个问题。

使用AOP应该是可行的,但棘手的部分是代理创建的顺序。如果您的方面组件将在管理事务的Spring代理之前被调用,那么您的自定义代码将在该事务之外被调用——这是您应该注意的一件事。除此之外,它应该是完全可行的。为了给您提供任何示例,我们需要查看您的代码示例,并对您尝试执行的操作进行更详细的解释。您不能使用Hibernate拦截器吗。您可以在执行前、执行后传递自定义查询。另外,由于您在同一事务中的拦截器中已经有sessionFactory,您也可以(确认这一点)获得回滚机制。使用aspect听起来也不错,但如果您希望它用于多个类,那么我相信Hibernate拦截器更有效…:-)@WeareBorg:在这个项目中没有hibernate可用,只有spring jdbc功能。@R4J:我提供了一些有问题的POC代码示例,您能指出提供的解决方案中的错误吗?问题解决了,我更改了