首页 文章

Spring事务不回滚

提问于
浏览
4

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

  • 'Get'方法抛出运行时异常

  • 我们正在使用 applicationContext.xml 中定义的 org.springframework.jdbc.datasource.DataSourceTransactionManagerMySQL datasource . beans 在 Beans.xml 中创建,导入 ApplicationContext.xml

DAO 图层中

  • @Transactional 注释

  • 我们在 applicationContext.xml 再次使用 <tx:annotation-driven transaction-manager="transactionManager"/>

  • 我们正在使用Spring 3.1

UPDATE

代码片段....

服务类 - 这与我所拥有的相似......我在使用和不使用@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 回答

  • 1

    @Transactional 的默认行为是在对象周围添加了一个代理事务行为(在您的示例中为 CustomerService ) . 从reference docs(向下滚动):

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

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

  • 3

    在您的情况下,解决方案将调用 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.
    

相关问题