Spring事务不回滚

时间:2013-04-23 10:41:42

标签: spring spring-transactions

我们有一个Spring Transaction回滚问题,其中回滚似乎不起作用。
在我用@Transactional注释的服务层方法中,我调用了三个不同的DAOImpl类来插入3条记录。
中间插入从第4个表中获取以填充描述字段但是这个失败了。我希望第一个插入回滚,但似乎没有发生。
几点:

  1. 'Get'方法抛出运行时例外
  2. 我们正在使用org.springframework.jdbc.datasource.DataSourceTransactionManager中定义的MySQL datasourceapplicationContext.xml。 Bean在Beans.xml中创建,导入ApplicationContext.xml
  3. @Transactional图层
  4. 中没有DAO注释
  5. 我们在<tx:annotation-driven transaction-manager="transactionManager"/>
  6. 中再次使用了applicationContext.xml
  7. 我们正在使用Spring 3.1
  8. 更新

    代码段....

    服务类 - 这与我的相似......我在使用和不使用@Autowired进行测试。在服务类中调用事务启用方法。

    public class CustomerService {
    
        //@Autowired
        CustomerOrderDAO customerOrderDAOImpl;
        //@Autowired
        CustomerItemDAO customerItemDAOImpl;
        //@Autowired
        CustomerPromotionDAO customerPromotionDAOImpl;
        //@Autowired
        PromotionDAO promotionDAOImpl;
    
        //other variables
    
    
        public CustomerOrder handleIncomingOrders(CustomerOrder customerOrder) {
            try {
                saveOrderDetails(customerOrder);
                .....
                return customerOrder;
            } catch (Exception e) //TO-DO catch proper exception 
            {
                //Send error response
                .......
                return customerOrder;
            }
        }
    
        @Transactional
        public void saveOrderDetails(CustomerOrder customerOrder) throws Exception {
                customerOrderDAOImpl.create(customerOrder);
                ....
                while (promotionsIterator.hasNext()) {
                    customerPromotion.setPromotionName(promotionDAOImpl.getName(customerOrder.getPromotionId));
                    customerPromotionDAOImpl.create(customerPromotion);
                }
                ......
                while (customerItemIterator.hasNext()) {
                    customerItemDAOImpl.create(customerItem);
                }
    
        }
    }
    

    有什么想法吗? 感谢。

2 个答案:

答案 0 :(得分:4)

@Transactional的默认行为是在对象周围添加了事务行为(代码中为CustomerService)。从reference docs(向下滚动):

  

在代理模式(默认设置)下,只拦截通过代理进入的外部方法调用。这意味着实际上,自调用目标对象中的一个方法调用目标对象的另一个方法,即使被调用的方法用@Transactional标记,也不会在运行时导致实际的事务。

在您的示例中,对handlingIncomingOrders()的外部调用将通过代理并命中目标对象(CustomerService的实例)。但是,对saveOrderDetails()的后续调用是目标对象内部的常规方法调用,因此永远不会调用代理中的事务行为。但是,如果从另一个类调用saveOrderDetails(),您会发现事务行为将按预期工作。

答案 1 :(得分:1)

您的案例中的解决方案是调用saveOrderDetails(customerOrder);作为proxyBean.saveOrderDetails(customerOrder);调用proxybean is the Object on which handleIncomingOrders`的位置。

如果CustomerServicesingleton(Defualt范围),则可以像将以下代码添加到Service类一样简单。 (将自引用添加为自动装配)

//@Autowired
CustomerService customerService; // As this is injected its a proxy

并在方法中将其用作

 public CustomerOrder handleIncomingOrders(CustomerOrder customerOrder) {
    try {
        customerService.saveOrderDetails(customerOrder);
        .....
        return customerOrder;
    } catch (Exception e) //TO-DO catch proper exception 
    {
        //Send error response
        .......
        return customerOrder;
    }
  }

如果其范围为Prototype,则可能的简单解决方案之一如下。

public CustomerOrder handleIncomingOrders(CustomerOrder customerOrder, CustomerService customerService) {
    try {
        customerService.saveOrderDetails(customerOrder);
        .....
        return customerOrder;
    } catch (Exception e) //TO-DO catch proper exception 
    {
        //Send error response
        .......
        return customerOrder;
    }
  }

您致电handleIncomingOrders的地方使用以下代码中建议的更改。

    bean.handleIncomingOrders(customerOrder); //Suppose this is old code 
Change it to 
    bean.handleIncomingOrders(customerOrder, bean);// THough it appears as we are sending reference to `THIS` as parameter whcihc can be unnecessary, in case of `Proxy`while inside your method `this` and `Passed reference` will point to different Obejects. 
相关问题