问题
I got this problem for a while and can't figure out what I am doing wrong. Here is the context:
- Spring 4.3.4.RELEASE
- Spring-data-jpa 1.10.6.RELEASE
- Hibernate 5.2.5.Final
- I'm using wildfly 10, starting via maven plugin
- configured datasource for JNDI lookup correctly
- using spring-data with @Repository on interfaces
- created entityManagerFactory as a spring bean (LocalContainerEntityManagerFactoryBean)
- as for transaction manager, I tried to use both 'tx:jta-transaction-manager' and spring bean (JtaTransactionManager)
- configured persistence.xml
- enable 'tx:annotation-driven'
So, I got a @Service class (SistemaBOImpl) that has a @Repository injected (SistemaDAO) and a test method for transactional behavior:
@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);
}
}
}
DAO
@Repository
@Transactional
public interface SistemaDAO extends DAO<Sistema, Long>, JpaRepository<Sistema, Long> {}
The problem is: Although 2nd save won't complete due to database constraints (and I did it on purpose, 1st save is commited and data is changed. I can't figure out why it is not rolling back all. What am I doing wrong?!?
Here are my other config file:
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>
Log/Stacktrace for 2nd save
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
回答1:
Check if the MySQL engine you are using is InnoDB. If you are using MyISAM, transaction is not supported.
回答2:
Got it folks!
After debugging for, like, a lot and searching for flaws on transaction configurations, I ended up seeing that all my Business weren't proxies. Well, that said I thought that it should be spring configuring my beans the issue and, for god sake :), was it. I got this spring-mvc config done wrong (WEB-INF/myco-servlet.xml):
<context:component-scan base-package="br.com.myco" />
<mvc:annotation-driven />
See the base-package? It was pointing to the same packages as in my applicationContext.xml:
<context:component-scan base-package="br.com.myco" />
I just had to change that config in myco-servlet.xml to the main mvc package:
<context:component-scan base-package="br.com.myco.service" />
And worked just fine!
Kudos for this question on stackoverflow also for the enlightment about the issue.
来源:https://stackoverflow.com/questions/41709151/transaction-not-rolling-back-spring-data-jta-jpa-wildfly10