Spring管理的事务提交它不应该(Spring managed Transaction commi

2019-10-20 14:08发布

在“的applicationContext-base.xml”我下面添加:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:util="http://www.springframework.org/schema/util"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc" 
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
        >

     .....

    <!-- transaction support-->
    <!-- PlatformTransactionMnager -->
    <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>
    <!-- enable transaction annotation support -->
    <tx:annotation-driven transaction-manager="txManager" />

我想设置的“控制器”交易的功能

@Controller
@RequestMapping("/ywdata")
public class YwController  extends BaseController{
....
@Transactional(timeout=1)
private void submitNewSXSQ(Map map, HttpServletRequest request, HttpServletResponse response) throws Exception {

    ...//STEP1 :do some db insert and update STEP1
    if(true)
        throw new Exception("test transaction ");

     ...//STEP2: do another db insert and update

我预计DB操作不应该被提交,因为我回来之前抛出一个异常。 但实际上不是。

Answer 1:

有你的代码的多个问题:

  • @Transactional私有方法不起作用
  • @Transactional@Controller注解类通常不工作
  • 被回滚不检查的异常进行

最后一个问题是很容易理解。 让我来解释前两个问题。 AOP在Spring的工作原理是这样的:

  • 应用程序上下文初始化之前,春季搜索需要方法拦截豆
  • 一个特殊的代理bean注册为这些豆...代理或者是动态的接口实现(JDK代理)或您的目标bean的动态子类(CGLIB代理)
  • 代理取代你的bean定义...原始定义被重新命名和标记为不符合自动装配(但它仍然存在于应用程序上下文)
  • 对代理的方法是非常愚蠢的 - 他们做的是拦截逻辑(即调用一些方面前/后/左右执行)并调用原来代理的目标bean的方法

为什么私有方法的问题:

  • 与JDK代理(默认):
    • @Transactional如果你有将无法正常工作@Transactional非接口方法(只接口方法上存在代理)
  • 与使用CGLIB:
    • @@Transactional ,如果你有将无法正常工作@Transactional私人或最终方法(唯一的非商业和非最终方法可以在动态的子类中重写)

为什么控制器问题:

  • Spring的RequestMappingHandlerMapping (豆负责将请求映射到你的@Controllers )要求的应用程序上下文来获取所有的豆类@Controller注解
    • 这可能会回到原来的类,而不是代理(我认为在春季JIRA这个错误,所以它可能是已经固定)
    • 在JDK代理的情况下,你需要将注释添加到界面(从而使代理注释)......这意味着你需要定义你的控制器接口

该怎么办:

  • 我建议你移动事务处理服务水平
  • 如果你希望你的交易围绕整个请求被包裹,你可能需要从你的灵感OpenSessionInViewFilter
  • 此外,我鼓励你把你的代码断点并检查堆栈跟踪并查找AOP代理。
  • 如果您仍想手动处理的代码一些随机的一部分的交易,你可以使用TransactionTemplate辅助类。


Answer 2:

从春天的文档,它是默认的行为:交易被标记为回滚只为unchecked异常。

参见第10.5.3 DOC



文章来源: Spring managed Transaction commits where it shouldn't