【问题标题】:Why transaction here is treated as two separate transactions?为什么这里的交易被视为两个独立的交易?
【发布时间】:2015-10-25 09:56:20
【问题描述】:

这里我在spring控制器中有以下方法

@Override
@Transactional
public Customer updateCustomer(Custom customer) throws Exception {
.....
depatmentService.updateDepartment(department);
..........


}

我在辅助类中有以下方法

@Override
@Transactional(readOnly = false)
public Department updateDepartment(Department department) throws Exception {
.....

}

我正在观察的是,一旦线程从方法updateDepartment 出来,该方法下的更改就会被提交。我不知道 为什么 ?默认传播是Propagation.REQUIRED,这意味着Support a current transaction, create a new one if none exists. 那么updateDepartment方法的事务怎么和updateCustomer方法分开呢

我正在使用 JPA(休眠实现)和 spring 事务。我也没有看到在 xml 中明确设置行为 propagation

spring配置中事务管理的相关部分

<bean id="txManager" class="org.springframework.orm.jpa.JpaTransactionManager">
  <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>


<tx:annotation-driven transaction-manager="txManager" />

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
  <property name="dataSource" ref="dataSource" />
  <property name="mappingResources" value="META-INF/custom-mappings.hbm.xml" />
  <property name="packagesToScan" value="com...,   ...Other packages" />
  <property name="jpaVendorAdapter">
    <bean id="jpaAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
         ...........
    </bean>
  </property>
  <property name="jpaProperties">
    <props>
      <prop key="org.hibernate.envers.default_schema">${jdbc.audit.schema}</prop>
      .........
      <prop key="hibernate.session_factory_name">SessionFactory</prop>
    </props>
  </property>
  <property name="jpaPropertyMap">
    <map>
      <entry key="javax.persistence.validation.factory">
        <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" />
      </entry>
    </map>
  </property>
</bean>

我也有控制器相关的配置文件

<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:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">

【问题讨论】:

  • 你检查过这个吗:stackoverflow.com/questions/4171605/…
  • 请添加 updateDepartment 正文。
  • 添加readOnly=false 更新客户。
  • 有人可以将此问题标记为重复吗?类似问题:stackoverflow.com/questions/2865055/…
  • 是的,我的意思是“这是唯一的……”。控制器由 spring 上下文处理,该上下文是配置事务管理的根上下文的子上下文。所以事务管理只适用于根上下文中的bean,控制器上的事务注解因此不起作用,因为控制器是由子上下文处理的。

标签: java spring jpa


【解决方案1】:

在控制器方法上使用@Transactional 注释并不常见。将事务分界置于服务级别的常见用法。

事务控制器是可能的,但有一些注意事项。首先,Spring 事务管理基于 Spring AOP,默认使用 JDK 代理。它在服务级别上运行良好,因为服务作为接口注入到控制器中。但是控制器不是作为接口注入的,所以它不会工作,你必须使用类目标代理和 CGLib 代理才能工作。据报道,使用 JDK 代理实现接口的控制器可以在某些 Spring 版本上工作,而在其他版本上则失败:请参阅 this other post

TL/DR:除非您真的不能将事务划分放在服务级别而不是控制器级别。

【讨论】:

  • 如果类实现了接口,我相信 Spring 使用 JDK 代理,但如果类没有实现任何接口,则自动使用 CGLIb。不是吗?所以对于控制器来说也不应该是问题
  • 不,它不是自动的。您必须在类级别使用 @Scope( proxyMode = ScopedProxyMode.TARGET_CLASS ) 明确声明它,并且您的类路径中必须有 cglib。
  • 但是当我检查我的任何服务时,我看到的就像MerService$$EEnhancerByCGLIB。我们正在使用&lt;aop:aspectj-autoproxy proxy-target-class="true" /&gt;。所以看起来它只为所有类启用了 cglib。不确定控制器?
  • Ok : &lt;aop:aspectj-autoproxy proxy-target-class="true" /&gt; 强制为整个应用程序使用 CGLib 代理。
  • 所以您的意思是说@Transactional 也应该适用于控制器,因为也会为控制器创建代理&lt;aop:aspectj-autoproxy proxy-target-class="true" /&gt;?如果是,则当线程退出服务方法时不应提交事务。对吧?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-21
  • 2020-07-30
  • 2017-01-27
  • 1970-01-01
  • 2018-06-12
  • 1970-01-01
相关资源
最近更新 更多