【问题标题】:(Transaction not rolling back) Spring-data, JTA, JPA, Wildfly10(事务不回滚)Spring-data、JPA、JPA、Wildfly 10
【发布时间】:2017-01-17 23:54:16
【问题描述】:

我有一段时间遇到这个问题,无法弄清楚我做错了什么。这是上下文:

  • Spring 4.3.4.RELEASE
  • Spring-data-jpa 1.10.6.RELEASE
  • 休眠 5.2.5.Final
  • 我使用的是 wildfly 10,从 maven 插件开始
  • 为 JNDI 查找正确配置了数据源
  • 在接口上使用带有 @Repository 的 spring-data
  • 将 entityManagerFactory 创建为 spring bean (LocalContainerEntityManagerFactoryBean)
  • 对于事务管理器,我尝试同时使用 'tx:jta-transaction-manager' 和 spring bean (JtaTransactionManager)
  • 配置persistence.xml
  • 启用“tx:annotation-driven”

所以,我得到了一个 @Service 类 (SistemaBOImpl),它注入了一个 @Repository (SistemaDAO) 和一个用于事务行为的测试方法:

    @Service
@Transactional(propagation = Propagation.SUPPORTS)
public class SistemaBOImpl extends AbstractBO<Sistema, Long> implements SistemaBO {

    @Autowired
    public SistemaBOImpl(SistemaDAO sistemaDAO) {
        super(sistemaDAO);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = { BusinessException.class })
    public void testTrans() throws BusinessException {
        try {
            final Sistema s = findOne(1L);
            s.setCodUsuAlt(SimpleDateFormat.getInstance().format(new Date()));
            s.setDatAlt(new Date());
            save(s); //1st save

            save(new Sistema()); //2nd save
        } catch (Exception e) {
            throw new RuntimeException(e);
            // throw new BusinessException(e);
        }
    }
}

@Repository
@Transactional
public interface SistemaDAO extends DAO<Sistema, Long>, JpaRepository<Sistema, Long> {}

问题是: 尽管由于数据库限制,第二次保存不会完成(我是故意这样做的,第一次保存已提交并且数据已更改。 我不明白为什么它没有全部回滚。 我做错了什么?!?

这是我的其他配置文件:

applicationContext.xml

<beans ... ommited namespace hell>
<context:annotation-config />

<context:component-scan base-package="br.com.myco" />

<tx:jta-transaction-manager />

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

<jpa:repositories base-package="br.com.myco" />

<jee:jndi-lookup id="dataSource" jndi-name="java:jboss/datasources/Myco_DB" />

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="jtaDataSource" ref="dataSource" />
    <property name="jpaVendorAdapter" >
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" >
            <property name="database" value="MYSQL" />
            <property name="showSql" value="true" />
        </bean>
    </property>
    <property name="persistenceUnitName" value="tof"/>
    <property name="packagesToScan" value="br.com.myco.tof"/>
</bean>

persistence.xml

<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd" version="2.1">
<persistence-unit name="myco" transaction-type="JTA">
    <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
    <jta-data-source>java:jboss/datasources/Myco_DB</jta-data-source>
    <class>br.com.abril.tof.domain.Sistema</class>
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
    <properties>
        <property name="hibernate.show_sql" value="false" />
        <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect" />
        <property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform"/>
        <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup" />
    </properties>
</persistence-unit>

web.xml

<web-app version="3.1" ...>

<display-name>MyCO</display-name>
<description>MyCO</description>

<!-- Carrega Spring -->
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<servlet>
    <servlet-name>myco</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>myco</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

<persistence-unit-ref>
    <persistence-unit-ref-name>jpa/EntityManager</persistence-unit-ref-name>
    <persistence-unit-name>myco</persistence-unit-name>
</persistence-unit-ref>

<session-config>
    <session-timeout>60</session-timeout>
</session-config>
</web-app>

第二次保存的日志/堆栈跟踪

Caused by: org.hibernate.HibernateException: Could not apply work
at org.hibernate.resource.transaction.backend.jta.internal.JtaIsolationDelegate.doTheWorkInNewTransaction(JtaIsolationDelegate.java:112)
at org.hibernate.resource.transaction.backend.jta.internal.JtaIsolationDelegate.delegateWork(JtaIsolationDelegate.java:65)
at org.hibernate.id.enhanced.TableStructure$1.getNextValue(TableStructure.java:125)
at org.hibernate.id.enhanced.NoopOptimizer.generate(NoopOptimizer.java:40)
at org.hibernate.id.enhanced.SequenceStyleGenerator.generate(SequenceStyleGenerator.java:412)
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:101)
at org.hibernate.jpa.event.internal.core.JpaPersistEventListener.saveWithGeneratedId(JpaPersistEventListener.java:67)
at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:189)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:132)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:58)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:775)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:748)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:753)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:1146)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:347)
at com.sun.proxy.$Proxy63.persist(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:298)
at com.sun.proxy.$Proxy63.persist(Unknown Source)
at org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:506)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:503)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:488)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:460)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:61)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282)
**at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)**
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
... 65 more

【问题讨论】:

  • 您拥有rollbackFor = BusinessException.class,但在出现错误时会抛出RuntimeException。仅当方法抛出 BusinessException 时才会发生自动回滚,但它不会,因此回滚不会发生(如预期的那样)。
  • 嗨,manish,我知道,这只是我所做的众多测试之一。我试过:省略“rollbackFor”配置并抛出两个异常,我尝试将 Runtime 和 BusinessException 放在该配置上等等......
  • 您能否调试您的应用程序以查看事务是否正在实际启动以进行测试?您可以在TransactionInterceptor 中放置断点来检查这一点。拦截器拦截对为 Spring 托管 bean 生成的代理的调用。使用您的 Spring 配置(特别是 &lt;tx:jta-transaction-manager /&gt;),代理将是 SistemaBO 的实例(因为默认代理是代理接口而不是类的 JDK 代理)。因此,除非SistemaBO@Transactional 声明了testTrans 方法,否则测试运行时可能没有事务在运行。
  • 我用第二次保存的堆栈跟踪更新了这个问题,它确实通过了 TransactionInterceptor(我在 之间标记)**在 org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor. java:96)

标签: hibernate jpa spring-data-jpa wildfly jta


【解决方案1】:

检查您使用的 MySQL 引擎是否为 InnoDB。如果您使用的是 MyISAM,则不支持交易。

【讨论】:

  • 嗨昆西,我正在使用 InnoDB。
  • 那么你使用的引擎支持事务吗?
  • 好吧,因为我正在使用 InnoDB... 支持事务。另外,我保证 MySQL 自动提交设置为 FALSE。
【解决方案2】:

明白了!

在调试了很多东西并搜索了事务配置的缺陷之后,我最终发现我的所有业务都不是代理。好吧,这就是说我认为应该是春天配置我的豆子的问题,看在上帝的份上:),是吗。 我把这个 spring-mvc 配置做错了(WEB-INF/myco-servlet.xml):

<context:component-scan base-package="br.com.myco" />
<mvc:annotation-driven />

看到基础包了吗?它指向与我的 applicationContext.xml 中相同的包:

<context:component-scan base-package="br.com.myco" />

我只需要将 myco-servlet.xml 中的配置更改为主 mvc 包:

<context:component-scan base-package="br.com.myco.service" />

而且工作得很好!

感谢question on stackoverflow 也感谢对这个问题的启发。

【讨论】:

    猜你喜欢
    • 2018-08-07
    • 2013-05-08
    • 2014-12-11
    • 1970-01-01
    • 2015-10-25
    • 2018-12-30
    • 1970-01-01
    • 2012-02-04
    相关资源
    最近更新 更多