Spring托管事务提交不应该提交的地方

时间:2014-07-29 09:28:09

标签: spring mybatis spring-transactions

in" 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" />

我想为&#34;控制器&#34;中的某个功能设置一个事务。

@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操作永远不应该提交,因为我在返回之前抛出异常。但实际上不是。

2 个答案:

答案 0 :(得分:8)

您的代码存在多个问题:

最后一个问题很容易理解。让我解释前两个问题。 Spring中的AOP就是这样的:

  • 在初始化应用程序上下文之前,Spring搜索需要方法拦截的bean
  • 为每个bean注册一个特殊的代理bean ...代理是目标bean的动态接口实现(JDK代理)或动态子类(CGLIB代理)
  • 代理替换了bean的定义...原始定义被重命名并标记为不符合自动装配的条件(但它仍然存在于应用程序上下文中)
  • 代理方法非常愚蠢 - 它们所做的只是拦截逻辑(即在执行前/后/周围调用某些方面)并调用原始代理目标bean方法

为什么私有方法有问题:

  • 使用JDK代理(默认):
      如果您在非接口方法上有@Transactional(代理上只有接口方法),则
    • @Transactional将无效。
  • 使用CGLIB代理:
      如果您对私有或最终方法@@Transactional(在动态子类中只能覆盖非私有和非最终方法),
    • @Transactional将无效。

为什么控制器有问题:

  • Spring RequestMappingHandlerMapping(负责将请求映射到您的@Controllers的bean)要求应用程序上下文获取带有@Controller注释的所有bean
    • 这可能会返回你的原始类,而不是代理(我认为在Spring JIRA中有一个bug,所以它可能已经修复了)
    • 在JDK代理的情况下,您需要将注释添加到接口(以便注释代理)...这意味着您需要为控制器定义接口

怎么做:

  • 我建议您将事务处理移至服务级别
  • 如果您希望将您的交易包含在整个请求中,您可以从OpenSessionInViewFilter获取灵感。
  • 另外,我建议您在代码中放置断点并检查堆栈跟踪并查找AOP代理。
  • 如果您仍想在代码的某些随机部分手动处理事务,可以使用TransactionTemplate帮助程序类。

答案 1 :(得分:1)

从Spring文档中,它是默认行为:事务被标记为仅针对未经检查的异常进行回滚。

参见doc

的第10.5.3节