Why is my transaction not active? javax.persistence.TransactionRequiredException: Executing an update/delete query
Solution 1
When you mark a method as @Transactional you are counting on JTA, yet - as stated by altanis - yet you define your persistence unit's transaction type as RESOURCE_LOCAL that is not JTA.
1) If you would like to use container managed transactions then change the transaction type, define your datasource as JTA Datasource in JBoss and change non-jta-data-source to jta-data-source
2) If you would like to manage your own transactions then keep the persistence.xml and datasource definition as it is but before any persist, merge, remove operations start a transaction by calling entitymanager.getTransaction().begin() and at the end of business unit, call either entitymanager.getTransaction().commit() or entitymanager.getTransaction().rollback(). In this case since you are managing transactions yourself, then there seems to be no point in starting a JTA transaction with @Transactional in updateProduct().
Solution 2
try changing transaction-type="RESOURCE_LOCAL" to transaction-type="JTA" in persistence.xml. Also you might need to remove element from persistence.xml.
ziggy
Updated on February 24, 2020Comments
-
ziggy over 4 years
I have a Spring Web Service (Spring-WS) application that i am trying to configure to use. The stack i am using is as follows
Spring 3 Spring-WS JPA with Hibernate as the provider JBoss 7.1*
The application is configured as follows:
persistence.xml
<persistence-unit name="myPersistenceUnit" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <jta-data-source>java:jboss/datasources/myDataSource</jta-data-source> <non-jta-data-source>java:jboss/datasources/myDataSource</non-jta-data-source> <class>myPackage.MyClass</class> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLInnoDBDialect"/> <property name="hibernate.connection.autocommit" value="true" /> <property name="hibernate.hbm2ddl.auto" value="validate"/> <property name="hibernate.show_sql" value="false"/> <property name="hibernate.cache.use_second_level_cache" value="true"/> <property name="hibernate.cache.provider_class" value="net.sf.ehcache.hibernate.SingletonEhCacheProvider"/> <property name="hibernate.search.default.directory_provider" value="org.hibernate.search.store.FSDirectoryProvider"/> <property name="hibernate.search.default.indexBase" value="./lucene/indexes"/> <property name="hibernate.search.default.batch.merge_factor" value="10"/> <property name="hibernate.search.default.batch.max_buffered_docs" value="10"/> </properties> </persistence-unit>
spring.xml - Entity Manger and Transaction manager
<context:annotation-config/> <context:component-scan base-package="com.mypackage"/> <bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" /> <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" /> <!-- Live database entity and transaction managers --> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" p:dataSource-ref="myDataSource"> <property name="persistenceUnitName" value="myPersistenceUnit" /> </bean> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager" p:entityManagerFactory-ref="entityManagerFactory" /> <tx:annotation-driven transaction-manager="transactionManager" />
Web.xml - To load the spring.xml file above
<context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/app-config.xml /WEB-INF/spring.xml /WEB-INF/spring-datasources.xml </param-value> </context-param>
spring-datasources.xml
<jee:jndi-lookup id="myDataSource" jndi-name="java:jboss/datasources/myDataSource"/>
In my DAO class i have the following definition for the entityManager.
@PersistenceContext(type=PersistenceContextType.TRANSACTION, unitName="myPersistenceUnit") protected EntityManager entityManager; @Transactional public void updateProduct(Product product) { // Save the document to the database update(product); }
The update method above simply calls a generic method with a call to
entityManager.merge(object);
Now when i test the above i find that it works if i am reading from the database but it does not work if i am writing to the database (i.e. create or update). If i try to write to the i get the following exception:
javax.persistence.TransactionRequiredException: Executing an update/delete query at org.hibernate.ejb.AbstractQueryImpl.executeUpdate(AbstractQueryImpl.java:96) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.springframework.orm.jpa.SharedEntityManagerCreator$DeferredQueryInvocationHandler.invoke(SharedEntityManagerCreator.java:310) at $Proxy96.executeUpdate(Unknown Source)
I am guessing the fact that i can read from the database it means that something is wrong in the configuration of the transaction manager. Any ideas?
Edit
OK i just re-read the above and noticed that the last bit is slightly wrong. The exception i have shown above only occurs if i use JPQL to issue an Update statement using
entityManager.createQuery
. If i try to update the entity usingentityManager.merge()
nothing actually happens. No exception is returned but the row is not updated.