У меня возникают проблемы с весенними программными транзакциями при использовании шаблона транзакции.Это всегда выдает следующее исключение. (Я использовал Spring 5.1.3 и Hibernate 5.3.7) Я пытался отладить, печатая состояние транзакции, которое показывает, что транзакция активна.
Обратите внимание: Эторабота с hibernate 4.3
javax.persistence.TransactionRequiredException: Executing an update/delete query
at org.hibernate.query.internal.AbstractProducedQuery.executeUpdate(AbstractProducedQuery.java:1586) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at com.rms.jobqueue.JobQueueImpl$1.doInTransaction(JobQueueImpl.java:184) ~[classes/:?]
at com.rms.jobqueue.JobQueueImpl$1.doInTransaction(JobQueueImpl.java:1) ~[classes/:?]
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140) ~[spring-tx-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at com.rms.jobqueue.JobQueueImpl.markQueueAsProcessing(JobQueueImpl.java:167) ~[classes/:?]
at com.rms.jobqueue.JobQueueImpl.dequeueIfReady(JobQueueImpl.java:229) ~[classes/:?]
at com.rms.jobqueue.JobQueueImpl.handleJobStageChange(JobQueueImpl.java:616) ~[classes/:?]
at com.rms.subscribe.subscriber.JobQueueStateSubscriber.handleEvent(JobQueueStateSubscriber.java:18) ~[classes/:?]
at com.rms.subscribe.publisher.EventDispatcher.notifySubscriberSynchronously(EventDispatcher.java:75) ~[classes/:?]
at com.rms.subscribe.publisher.SynchronousPublisherImpl.broadcast(SynchronousPublisherImpl.java:96) ~[classes/:?]
at com.rms.event.RmsEventListener.onReceivingEntityEvent(RmsEventListener.java:35) ~[classes/:?]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_161]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_161]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_161]
at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_161]
Вот пример кода, который вызывает проблему: -
public boolean markQueueAsProcessing(Job qj) {
return txTemplate.execute(new TransactionCallback<Boolean>() {
@Override
public Boolean doInTransaction(TransactionStatus transactionStatus) {
String hql = "UPDATE Job qj SET qj.stage = :targetStage, qj.stageChangeDate = :stageChangeDate WHERE qj.stage = :requiredStage AND qj.id = :qjId";
Date now = new Date();
System.out.println("Current Transaction Status => " + TransactionSynchronizationManager.isActualTransactionActive());
boolean processingSuccess = sessionFactory.getCurrentSession().createQuery(hql)
.setParameter("targetStage", QueStage.PROCESSING.name())
.setParameter("requiredStage", QueStage.QUEUED.name())
.setParameter("qjId", qj.getId())
.setParameter("stageChangeDate", now)
.executeUpdate() > 0;
if (processingSuccess) {
qj.setStageChangeDate(now);
qj.setStage(QueStage.PROCESSING.name());
}
return processingSuccess;
}
});
}
Файл Hibernate Cfg: -
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.temp.use_jdbc_metadata_defaults">false</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
<property name="hibernate.format_sql">false</property>
<property name="hibernate.show_sql">false</property>
<property name="hibernate.max_fetch_depth">3</property>
<property name="hibernate.cache.use_second_level_cache">true</property>
<property name="hibernate.cache.use_query_cache">true</property>
<property name="hibernate.cache.region.factory_class">org.hibernate.cache.jcache.JCacheRegionFactory</property>
<property name="hibernate.javax.cache.provider">org.ehcache.jsr107.EhcacheCachingProvider</property>
<!--<property name="hibernate.cache.default_cache_concurrency_strategy">read-write</property>-->
<!--<property name="hibernate.javax.cache.uri">file:///C:/Dropbox/nnooka/RMS/RMSv2/src/main/resources/ehcache.xml</property>-->
<property name="hibernate.connection.CharSet">utf8</property>
<property name="hibernate.connection.characterEncoding">utf8</property>
<property name="hibernate.connection.useUnicode">true</property>
<property name="hibernate.jdbc.batch_size">30</property>
<property name="hibernate.order_inserts">true</property>
<property name="hibernate.order_updates">true</property>
<property name="hibernate.jdbc.batch_versioned_data">true</property>
<property name="hibernate.allow_update_outside_transaction">true</property>
<!-- <property name="hibernate.generate_statistics">true</property> -->
</session-factory>
</hibernate-configuration>
Вот конфигурация Spring xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
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/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.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
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd" >
<bean id="hikariConfig" class="com.zaxxer.hikari.HikariConfig">
<property name="poolName" value="RmsHikariCP" />
<property name="registerMbeans" value="true"/>
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="jdbcUrl" value="jdbc:mysql://xxxx:3306/apt_db?autoReconnect=true&zeroDateTimeBehavior=convertToNull&useUnicode=true&characterEncoding=utf-8" />
<property name="username" value="xxxxx"/>
<property name="password" value="hz6yJJas"/>
<property name="maximumPoolSize" value="180"/>
<property name="minimumIdle" value="30"/>
<property name="idleTimeout" value="300000"/>
<property name="connectionTimeout" value="120000"/>
<property name="leakDetectionThreshold" value="600000"/>
</bean>
<bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource" destroy-method="close">
<constructor-arg ref="hikariConfig" />
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="packagesToScan">
<list>
<value>com.rms.model</value>
</list>
</property>
<property name="configLocation" value="classpath:hibernate.cfg.xml" />
</bean>
<!-- A transaction manager for working with Hibernate SessionFactories -->
<bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean
</bean>
<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"></property>
<property name="isolationLevelName" value="ISOLATION_READ_COMMITTED"/>
</bean>
</beans>