我问了this问题,并实施了答案。它工作正常,但现在我正在处理更多数据,但未按预期工作。说明:
我正在与JMS建立集成。在集成过程结束之前,无论如何我都必须记录集成。为此,我建立了一个@Service
,可以将日志保存在新事务中。如果我使用该服务,则会遇到异常。如果我在同一个bean中执行服务的相同逻辑,则可以正常工作。让我显示一些代码:
听众
public class JMSListenerIntegration {
@Autowired
private IntegrationHandler integrationHandler;
@Autowired
private LogService logService;
@Autowired
private IntegrationLogRepository logRepository; // extends JpaRepository
@JmsListener(...)
public void onReceive(Message message) {
List<Dto> dtos = // Unmarshall the message
// A log for this integration already exists
// On receiving a message, it changes status from RUNNING to OK or NOK
IntegrationLog log = logRepository.findAlreadyExistingLog();
try {
// The integration handler persist 100+ records, each one in a new transaction
boolean success = integrationHandler.handle(dtos);
if (success)
log.setStatus("OK");
else
log.setStatus("NOK");
} catch (Exception e) {
log.setStatus("NOK");
} finally {
logService.save(log);
// this.saveLog(log); // THIS WORKS
}
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void saveLog(IntegrationLog log) {
logRepository.saveAndFlush(log);
}
}
LogService
@Service
public class LogService {
@Autowired
private IntegrationLogRepository logRepository;
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void save(IntegrationLog log) {
logRepository.saveAndFlush(log);
}
}
如果我使用在saveLog()
上定义的JMSListenerIntegration
函数运行代码,则可以正常工作。相反,如果我尝试使用我的LogService
类,则它不起作用。我在日志上看到一个用于选择日志的休眠查询,然后在20秒钟后出现错误:
2019-01-02 20:21:35.649 WARN 21112 --- [ (self-tuning)'] onizationCallbackCoordinatorTrackingImpl : HHH000451: Transaction afterCompletion called by a background thread; delaying afterCompletion processing until the original thread can handle it. [status=4]
2019-01-02 20:21:35.652 WARN 21112 --- [enerContainer-1] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 0, SQLState: null
2019-01-02 20:21:35.652 ERROR 21112 --- [enerContainer-1] o.h.engine.jdbc.spi.SqlExceptionHelper : The transaction is no longer active - status: 'Marked rollback. [Reason=weblogic.transaction.internal.TimedOutException: Transaction timed out after 31 seconds
BEA1-36996D3224E23057A4BD]'. No further JDBC access is allowed within this transaction.
2019-01-02 20:21:35.657 INFO 21112 --- [enerContainer-1] o.h.e.internal.DefaultLoadEventListener : HHH000327: Error performing load command : org.hibernate.exception.GenericJDBCException: could not load an entity: [com.example.models.IntegrationLog#6]
2019-01-02 20:21:35.692 WARN 21112 --- [enerContainer-1] o.s.j.l.DefaultMessageListenerContainer : Execution of JMS message listener failed, and no ErrorHandler has been set.
org.springframework.orm.jpa.JpaSystemException: could not load an entity: [com.example.models.IntegrationLog#6]; nested exception is org.hibernate.exception.GenericJDBCException: could not load an entity: [com.example.models.IntegrationLog#6]
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:333) ~[spring-orm-4.3.18.RELEASE.jar:4.3.18.RELEASE]
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:244) ~[spring-orm-4.3.18.RELEASE.jar:4.3.18.RELEASE]
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:525) ~[spring-orm-4.3.18.RELEASE.jar:4.3.18.RELEASE]
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59) ~[spring-tx-4.3.18.RELEASE.jar:4.3.18.RELEASE]
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:209) ~[spring-tx-4.3.18.RELEASE.jar:4.3.18.RELEASE]
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:147) ~[spring-tx-4.3.18.RELEASE.jar:4.3.18.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.18.RELEASE.jar:4.3.18.RELEASE]
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:133) ~[spring-data-jpa-1.11.14.RELEASE.jar:na]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.18.RELEASE.jar:4.3.18.RELEASE]
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) ~[spring-aop-4.3.18.RELEASE.jar:4.3.18.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.18.RELEASE.jar:4.3.18.RELEASE]
at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:57) ~[spring-data-commons-1.13.14.RELEASE.jar:na]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.18.RELEASE.jar:4.3.18.RELEASE]
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213) ~[spring-aop-4.3.18.RELEASE.jar:4.3.18.RELEASE]
at com.sun.proxy.$Proxy400.save(Unknown Source) ~[na:na]
at com.example.services.IntegrationLogService.save(IntegrationLogService.kt:20) ~[_wl_cls_gen.jar:na]
at com.example.services.IntegrationLogService$$FastClassBySpringCGLIB$$98a7fdd9.invoke(<generated>) ~[_wl_cls_gen.jar:na]
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) ~[spring-core-4.3.18.RELEASE.jar:4.3.18.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:736) ~[spring-aop-4.3.18.RELEASE.jar:4.3.18.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) ~[spring-aop-4.3.18.RELEASE.jar:4.3.18.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99) ~[spring-tx-4.3.18.RELEASE.jar:4.3.18.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282) ~[spring-tx-4.3.18.RELEASE.jar:4.3.18.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) ~[spring-tx-4.3.18.RELEASE.jar:4.3.18.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.18.RELEASE.jar:4.3.18.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:671) ~[spring-aop-4.3.18.RELEASE.jar:4.3.18.RELEASE]
at com.example.services.IntegrationLogService$$EnhancerBySpringCGLIB$$9eee6d68.save(<generated>) ~[_wl_cls_gen.jar:na]
at com.example.integrations.listeners.MalhaJmsListener.onReceive(MalhaJmsListener.kt:88) ~[_wl_cls_gen.jar:na]
at com.example.integrations.listeners.MalhaJmsListener$$FastClassBySpringCGLIB$$1357be2d.invoke(<generated>) ~[_wl_cls_gen.jar:na]
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) ~[spring-core-4.3.18.RELEASE.jar:4.3.18.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:667) ~[spring-aop-4.3.18.RELEASE.jar:4.3.18.RELEASE]
at com.example.integrations.listeners.MalhaJmsListener$$EnhancerBySpringCGLIB$$c9de82e4.onReceive(<generated>) ~[_wl_cls_gen.jar:na]
at com.example.integrations.listeners.ListenersManager$startupListeners$1.onMessage(ListenersManager.kt:42) ~[_wl_cls_gen.jar:na]
at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:744) ~[spring-jms-4.3.18.RELEASE.jar:4.3.18.RELEASE]
at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:682) ~[spring-jms-4.3.18.RELEASE.jar:4.3.18.RELEASE]
at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:649) ~[spring-jms-4.3.18.RELEASE.jar:4.3.18.RELEASE]
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:317) [spring-jms-4.3.18.RELEASE.jar:4.3.18.RELEASE]
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:235) [spring-jms-4.3.18.RELEASE.jar:4.3.18.RELEASE]
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1168) [spring-jms-4.3.18.RELEASE.jar:4.3.18.RELEASE]
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:1160) [spring-jms-4.3.18.RELEASE.jar:4.3.18.RELEASE]
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:1057) [spring-jms-4.3.18.RELEASE.jar:4.3.18.RELEASE]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_192]
Caused by: org.hibernate.exception.GenericJDBCException: could not load an entity: [com.example.models.IntegrationLog#6]
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:47) ~[hibernate-core-5.1.16.Final.jar:5.1.16.Final]
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:111) ~[hibernate-core-5.1.16.Final.jar:5.1.16.Final]
at org.hibernate.loader.Loader.loadEntity(Loader.java:2213) ~[hibernate-core-5.1.16.Final.jar:5.1.16.Final]
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:60) ~[hibernate-core-5.1.16.Final.jar:5.1.16.Final]
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:50) ~[hibernate-core-5.1.16.Final.jar:5.1.16.Final]
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:4083) ~[hibernate-core-5.1.16.Final.jar:5.1.16.Final]
at org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:508) ~[hibernate-core-5.1.16.Final.jar:5.1.16.Final]
at org.hibernate.event.internal.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:478) ~[hibernate-core-5.1.16.Final.jar:5.1.16.Final]
at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:219) ~[hibernate-core-5.1.16.Final.jar:5.1.16.Final]
at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:278) ~[hibernate-core-5.1.16.Final.jar:5.1.16.Final]
at org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad(DefaultLoadEventListener.java:121) ~[hibernate-core-5.1.16.Final.jar:5.1.16.Final]
at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:89) ~[hibernate-core-5.1.16.Final.jar:5.1.16.Final]
at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1142) ~[hibernate-core-5.1.16.Final.jar:5.1.16.Final]
at org.hibernate.internal.SessionImpl.access$2600(SessionImpl.java:167) ~[hibernate-core-5.1.16.Final.jar:5.1.16.Final]
at org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.doLoad(SessionImpl.java:2762) ~[hibernate-core-5.1.16.Final.jar:5.1.16.Final]
at org.hibernate.internal.SessionImpl$IdentifierLoadAccessImpl.load(SessionImpl.java:2741) ~[hibernate-core-5.1.16.Final.jar:5.1.16.Final]
at org.hibernate.internal.SessionImpl.get(SessionImpl.java:983) ~[hibernate-core-5.1.16.Final.jar:5.1.16.Final]
at org.hibernate.event.internal.DefaultMergeEventListener.entityIsDetached(DefaultMergeEventListener.java:289) ~[hibernate-core-5.1.16.Final.jar:5.1.16.Final]
at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:169) ~[hibernate-core-5.1.16.Final.jar:5.1.16.Final]
at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:68) ~[hibernate-core-5.1.16.Final.jar:5.1.16.Final]
at org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:843) ~[hibernate-core-5.1.16.Final.jar:5.1.16.Final]
at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:825) ~[hibernate-core-5.1.16.Final.jar:5.1.16.Final]
at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:830) ~[hibernate-core-5.1.16.Final.jar:5.1.16.Final]
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.merge(AbstractEntityManagerImpl.java:1161) ~[hibernate-entitymanager-5.1.0.Final.jar:5.1.0.Final]
at sun.reflect.GeneratedMethodAccessor252.invoke(Unknown Source) ~[na:na]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_192]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_192]
at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:347) ~[spring-orm-4.3.18.RELEASE.jar:4.3.18.RELEASE]
at com.sun.proxy.$Proxy386.merge(Unknown Source) ~[na:na]
at sun.reflect.GeneratedMethodAccessor252.invoke(Unknown Source) ~[na:na]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_192]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_192]
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:300) ~[spring-orm-4.3.18.RELEASE.jar:4.3.18.RELEASE]
at com.sun.proxy.$Proxy386.merge(Unknown Source) ~[na:na]
at org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:511) ~[spring-data-jpa-1.11.14.RELEASE.jar:na]
at sun.reflect.GeneratedMethodAccessor254.invoke(Unknown Source) ~[na:na]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_192]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_192]
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:515) ~[spring-data-commons-1.13.14.RELEASE.jar:na]
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:500) ~[spring-data-commons-1.13.14.RELEASE.jar:na]
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:477) ~[spring-data-commons-1.13.14.RELEASE.jar:na]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.18.RELEASE.jar:4.3.18.RELEASE]
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:56) ~[spring-data-commons-1.13.14.RELEASE.jar:na]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.18.RELEASE.jar:4.3.18.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99) ~[spring-tx-4.3.18.RELEASE.jar:4.3.18.RELEASE]
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282) ~[spring-tx-4.3.18.RELEASE.jar:4.3.18.RELEASE]
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) ~[spring-tx-4.3.18.RELEASE.jar:4.3.18.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.3.18.RELEASE.jar:4.3.18.RELEASE]
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136) ~[spring-tx-4.3.18.RELEASE.jar:4.3.18.RELEASE]
... 35 common frames omitted
Caused by: java.sql.SQLException: The transaction is no longer active - status: 'Marked rollback. [Reason=weblogic.transaction.internal.TimedOutException: Transaction timed out after 30 seconds
BEA1-01E60652F53A3057A4BD]'. No further JDBC access is allowed within this transaction.
at weblogic.jdbc.wrapper.JTSConnection.checkIfRolledBack(JTSConnection.java:202) ~[weblogic.server.merged.jar:12.1.3.0.0]
at weblogic.jdbc.wrapper.JTSConnection.checkConnection(JTSConnection.java:220) ~[weblogic.server.merged.jar:12.1.3.0.0]
at weblogic.jdbc.wrapper.ResultSet.preInvocationHandler(ResultSet.java:95) ~[weblogic.server.merged.jar:12.1.3.0.0]
at weblogic.jdbc.wrapper.ResultSet_weblogic_jdbc_sqlserverbase_ddeb.next(Unknown Source) ~[weblogic.server.merged.jar:12.1.3.0.0]
at org.hibernate.loader.Loader.processResultSet(Loader.java:974) ~[hibernate-core-5.1.16.Final.jar:5.1.16.Final]
at org.hibernate.loader.Loader.doQuery(Loader.java:936) ~[hibernate-core-5.1.16.Final.jar:5.1.16.Final]
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:342) ~[hibernate-core-5.1.16.Final.jar:5.1.16.Final]
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:312) ~[hibernate-core-5.1.16.Final.jar:5.1.16.Final]
at org.hibernate.loader.Loader.loadEntity(Loader.java:2209) ~[hibernate-core-5.1.16.Final.jar:5.1.16.Final]
... 81 common frames omitted
为什么会这样?
谢谢
编辑
根据评论建议,我将LogService
更改为:
@Service
public class LogService {
@Autowired
private IntegrationLogRepository logRepository;
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void save(IntegrationLog plainLog) {
IntegrationLog log = logRepository.findOne(plainLog.getId());
log.setStatus(plainLog.getStatus());
log.setFoo(plainLog.getFoo());
// ...
logRepository.saveAndFlush(log);
}
}
我仍然遇到相同的错误。我开始认为这与先前在integrationHandler.handle(dtos)
上进行的操作有关。用这种方法,我坚持了很多记录。逻辑如下:
public boolean handle(List<Dto> dtos) {
boolean result = true;
for (Dto dto in dtos) {
try {
Foo foo = new Foo();
foo.setProp1(dto.getProp1());
foo.setProp2(dto.getProp2());
saveFoo(foo);
} catch (Exception e) {
logger.error(e.getMessage());
result = false;
}
}
return result;
}
// Now I know this is not running in its own transaction, right?
@Transactional(propagation = Propagation.REQUIRES_NEW)
public saveFoo(Foo foo) {
fooRepository.save(foo);
}
如果我不调用handle()
方法(因此不执行持久操作),则LogService
可以正常工作。我只能想象保存Foo
的事务花费的时间太长,而findOne
的事务被gettint超时(找不到原因)给could not load an entity
(我什至尝试调用findOne(6)
,这是我数据库中的有效ID)。也许这不是持久保存数据的正确方法...?真是丢在这里的家伙。任何帮助表示赞赏:/