6

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

  1. 'Get' 方法引发运行时异常
  2. 我们使用org.springframework.jdbc.datasource.DataSourceTransactionManagerMySQL datasource定义在applicationContext.xml. Beans被创建在Beans.xml其中被导入ApplicationContext.xml
  3. 图层中没有@Transactional注释DAO
  4. 我们<tx:annotation-driven transaction-manager="transactionManager"/>applicationContext.xml
  5. 我们正在使用 Spring 3.1

更新

代码片段....

服务类- 这与我所拥有的类似......我在有和没有@Autowired 的情况下进行了测试。在服务类中调用事务启用方法。

公共类客户服务{

    //@自动连线
    CustomerOrderDAO customerOrderDAOImpl;
    //@自动连线
    CustomerItemDAO customerItemDAOImpl;
    //@自动连线
    CustomerPromotionDAO customerPromotionDAOImpl;
    //@自动连线
    推广DAO 推广DAOImpl;

    //其他变量


    公共客户订单handleIncomingOrders(客户订单客户订单){
        尝试 {
            saveOrderDetails(customerOrder);
            ......
            返回客户订单;
        } catch (Exception e) //TO-DO 捕获正确的异常
        {
            //发送错误响应
            …………
            返回客户订单;
        }
    }

    @Transactional
    公共无效 saveOrderDetails(CustomerOrder customerOrder) 抛出异常 {
            customerOrderDAOImpl.create(customerOrder);
            ……
            while (promotionsIterator.hasNext()) {
                customerPromotion.setPromotionName(promotionDAOImpl.getName(customerOrder.getPromotionId));
                customerPromotionDAOImpl.create(customerPromotion);
            }
            ……
            while (customerItemIterator.hasNext()) {
                customerItemDAOImpl.create(customerItem);
            }

    }
}

任何的想法?谢谢。

4

2 回答 2

7

的默认行为@Transactional是在对象周围添加了事务行为(CustomerService在您的示例中)。从参考文档(向下滚动):

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

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

于 2013-04-24T05:51:07.823 回答
2

在您的情况下,解决方案将调用saveOrderDetails(customerOrder); 为调用proxyBean.saveOrderDetails(customerOrder);handleIncomingOrdersproxybean is the Object on which的位置。

如果CustomerServicesingleton(默认范围),它可以像将以下代码添加到服务类一样简单。(将自引用添加为自动装配)

//@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. 
于 2013-04-24T10:50:04.950 回答