查询资料也都说明是save方法缺少可用的事物但@Transactional的注解无法解决问题,特别头疼
JmsConfig复制了课程源码没有做改动
Dao接口直接继承JpaRepository
Controller代码:
@PostMapping(path = "/test")
public void test(@RequestParam Long goodsId) throws Exception{
jmsTemplate.convertAndSend("goods:msg:handle",goodsId);
}
Service代码:
@JmsListener(destination = "goods:msg:handle", containerFactory = "msgFactory")
@Transactional
public void dealStock(Long goodsId) throws RuntimeException{
log.info("goodsId:{} start deal stock...",goodsId);
//扣除库存
Goods goods = goodsRepository.findById(goodsId).get();
if (goods.getStockNum() < 1) {
throw new RuntimeException("库存不足1件");
// throw new Error("严重错误");
}
goods.setStockNum(goods.getStockNum() - 1);
goodsRepository.save(goods);
}
日志信息:
2019-01-17 11:43:54.858 INFO 3340 --- [nio-8080-exec-2] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2019-01-17 11:43:54.859 INFO 3340 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2019-01-17 11:43:54.864 INFO 3340 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet : Completed initialization in 5 ms
2019-01-17 11:43:54.874 DEBUG 3340 --- [nio-8080-exec-2] o.j.s.OpenEntityManagerInViewInterceptor : Opening JPA EntityManager in OpenEntityManagerInViewInterceptor
2019-01-17 11:43:54.888 DEBUG 3340 --- [nio-8080-exec-2] o.s.j.c.CachingConnectionFactory : Registering cached JMS Session for mode 1: ActiveMQSession {id=ID:SC-201608081038-60169-1547696626157-4:1:2,started=true} java.lang.Object@6ecb360
2019-01-17 11:43:54.888 DEBUG 3340 --- [nio-8080-exec-2] o.springframework.jms.core.JmsTemplate : Executing callback on JMS Session: Cached JMS Session: ActiveMQSession {id=ID:SC-201608081038-60169-1547696626157-4:1:2,started=true} java.lang.Object@6ecb360
2019-01-17 11:43:54.892 DEBUG 3340 --- [nio-8080-exec-2] o.s.j.c.CachingConnectionFactory : Registering cached JMS MessageProducer for destination [queue://goods:msg:handle]: ActiveMQMessageProducer { value=ID:SC-201608081038-60169-1547696626157-4:1:2:1 }
2019-01-17 11:43:54.896 DEBUG 3340 --- [nio-8080-exec-2] o.springframework.jms.core.JmsTemplate : Sending created message: ActiveMQObjectMessage {commandId = 0, responseRequired = false, messageId = null, originalDestination = null, originalTransactionId = null, producerId = null, destination = null, transactionId = null, expiration = 0, timestamp = 0, arrival = 0, brokerInTime = 0, brokerOutTime = 0, correlationId = null, replyTo = null, persistent = false, type = null, priority = 0, groupID = null, groupSequence = 0, targetConsumerId = null, compressed = false, userID = null, content = org.apache.activemq.util.ByteSequence@4c456670, marshalledProperties = null, dataStructure = null, redeliveryCounter = 0, size = 0, properties = null, readOnlyProperties = false, readOnlyBody = false, droppable = false, jmsXGroupFirstForConsumer = false}
2019-01-17 11:43:54.904 DEBUG 3340 --- [enerContainer-1] o.s.j.l.DefaultMessageListenerContainer : Received message of type [class org.apache.activemq.command.ActiveMQObjectMessage] from consumer [ActiveMQMessageConsumer { value=ID:SC-201608081038-60169-1547696626157-4:1:1:1, started=true }] of transactional session [Cached JMS Session: ActiveMQSession {id=ID:SC-201608081038-60169-1547696626157-4:1:1,started=true} java.lang.Object@1d3c0b1d]
2019-01-17 11:43:54.904 DEBUG 3340 --- [enerContainer-1] .s.j.l.a.MessagingMessageListenerAdapter : Processing [org.springframework.jms.listener.adapter.AbstractAdaptableMessageListener$MessagingMessageConverterAdapter$LazyResolutionMessage@5e154eb8]
2019-01-17 11:43:54.909 DEBUG 3340 --- [enerContainer-1] o.s.j.connection.JmsTransactionManager : Participating in existing transaction
2019-01-17 11:43:54.912 INFO 3340 --- [enerContainer-1] c.y.e.demotrans.service.OrderService : goodsId:1 start deal stock...
2019-01-17 11:43:54.915 DEBUG 3340 --- [enerContainer-1] o.s.j.connection.JmsTransactionManager : Participating in existing transaction
2019-01-17 11:43:54.916 DEBUG 3340 --- [nio-8080-exec-2] o.j.s.OpenEntityManagerInViewInterceptor : Closing JPA EntityManager in OpenEntityManagerInViewInterceptor
2019-01-17 11:43:54.918 DEBUG 3340 --- [enerContainer-1] tor$SharedEntityManagerInvocationHandler : Creating new EntityManager for shared EntityManager invocation
2019-01-17 11:43:54.924 DEBUG 3340 --- [enerContainer-1] org.hibernate.SQL : select goods0_.id as id1_0_0_, goods0_.goods_name as goods_na2_0_0_, goods0_.stock_num as stock_nu3_0_0_ from goods goods0_ where goods0_.id=?
2019-01-17 11:43:54.956 DEBUG 3340 --- [enerContainer-1] o.s.j.connection.JmsTransactionManager : Participating in existing transaction
2019-01-17 11:43:54.958 DEBUG 3340 --- [enerContainer-1] o.s.j.connection.JmsTransactionManager : Participating transaction failed - marking existing transaction as rollback-only
2019-01-17 11:43:54.961 DEBUG 3340 --- [enerContainer-1] o.s.j.connection.JmsTransactionManager : Participating transaction failed - marking existing transaction as rollback-only
2019-01-17 11:43:54.962 DEBUG 3340 --- [enerContainer-1] o.s.j.l.DefaultMessageListenerContainer : Rolling back transaction because of listener exception thrown: org.springframework.jms.listener.adapter.ListenerExecutionFailedException: Listener method 'public void com.yangqi.example.demotrans.service.OrderService.dealStock(java.lang.Long) throws java.lang.RuntimeException' threw exception; nested exception is org.springframework.dao.InvalidDataAccessApiUsageException: No EntityManager with actual transaction available for current thread - cannot reliably process 'merge' call; nested exception is javax.persistence.TransactionRequiredException: No EntityManager with actual transaction available for current thread - cannot reliably process 'merge' call
2019-01-17 11:43:54.964 WARN 3340 --- [enerContainer-1] o.s.j.l.DefaultMessageListenerContainer : Execution of JMS message listener failed, and no ErrorHandler has been set.
org.springframework.jms.listener.adapter.ListenerExecutionFailedException: Listener method 'public void com.yangqi.example.demotrans.service.OrderService.dealStock(java.lang.Long) throws java.lang.RuntimeException' threw exception; nested exception is org.springframework.dao.InvalidDataAccessApiUsageException: No EntityManager with actual transaction available for current thread - cannot reliably process 'merge' call; nested exception is javax.persistence.TransactionRequiredException: No EntityManager with actual transaction available for current thread - cannot reliably process 'merge' call
at org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:122)
at org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter.onMessage(MessagingMessageListenerAdapter.java:77)
at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:736)
at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:696)
at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:674)
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:318)
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:245)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1189)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:1179)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:1076)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.dao.InvalidDataAccessApiUsageException: No EntityManager with actual transaction available for current thread - cannot reliably process 'merge' call; nested exception is javax.persistence.TransactionRequiredException: No EntityManager with actual transaction available for current thread - cannot reliably process 'merge' call
at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:402)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:255)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:527)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:153)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:135)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:93)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:61)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
at com.sun.proxy.$Proxy90.save(Unknown Source)
at com.yangqi.example.demotrans.service.OrderService.dealStock(OrderService.java:76)
at com.yangqi.example.demotrans.service.OrderService$$FastClassBySpringCGLIB$$e8f9e435.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:749)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:294)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
at com.yangqi.example.demotrans.service.OrderService$$EnhancerBySpringCGLIB$$580768e4.dealStock(<generated>)
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:498)
at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:170)
at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:120)
at org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:114)
... 10 common frames omitted
Caused by: javax.persistence.TransactionRequiredException: No EntityManager with actual transaction available for current thread - cannot reliably process 'merge' call
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:292)
at com.sun.proxy.$Proxy85.merge(Unknown Source)
at org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:492)
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:498)
at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:359)
at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:200)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:644)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:608)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.lambda$invoke$3(RepositoryFactorySupport.java:595)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:595)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:59)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:294)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139)
... 36 common frames omitted
2019-01-17 11:43:54.965 DEBUG 3340 --- [enerContainer-1] o.s.j.connection.JmsTransactionManager : Transactional code has requested rollback
2019-01-17 11:43:54.965 DEBUG 3340 --- [enerContainer-1] o.s.j.connection.JmsTransactionManager : Initiating transaction rollback
2019-01-17 11:43:54.965 DEBUG 3340 --- [enerContainer-1] o.s.j.connection.JmsTransactionManager : Rolling back JMS transaction on Session [Cached JMS Session: ActiveMQSession {id=ID:SC-201608081038-60169-1547696626157-4:1:1,started=true} java.lang.Object@1d3c0b1d]