请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

添加JmsConfig配置后执行JpaRepository的save方法时出现异常

查询资料也都说明是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]

正在回答

2回答

我看你是在JTA多数据源的章节提的问题,我还以为是使用JTA事务管理,但是在日志里面看不到JTA事务相关的信息。

你的问题描述里面说使用JmsConfig配置,应该是配置了Jms的事务管理器,从日志里面也能看出来,JmsTransactionManager在起作用,但是应该是没有数据库的事务相关的日志。所以,我猜你是你设置了Jms的事务管理,没有数据库的。

如果是这样,你可以看一下第六章,有介绍怎么在spring中不用JTA的情况下处理多数据源的分布式事务。简单来说,就是我们要使用Jpa的事务管理,然后让jms的事务根据Jpa事务进行同步,也就是Jpa事务提交的时候,通过spring来触发Jms的事务的提交。

0 回复 有任何疑惑可以回复我~
  • 提问者 qq_慕神9216905 #1
    在你的提醒下我又仔细看了一眼日志,问题的确是JtaTransactionManager没起作用,取消JmsTransactionManager的注入后Jta的事物生效。
    同时msgFactory要去除factory.setCacheLevelName("CACHE_CONNECTION");的配置,否则会在向MQ发送消息的时候出现超时回滚的情况,原因不明
    回复 有任何疑惑可以回复我~ 2019-01-21 15:50:01
  • 大漠风 回复 提问者 qq_慕神9216905 #2
    我当时加`CACHE_CONNECTION `,是因为在我的环境下jms的connection链接每次发完消息就关闭了,这时候再进行事务同步的时候,就提示链接关闭。
    由于当时是使用的内置的activeMQ,方便演示,这个应该也是跟这种运行方式有关。而且,不同的版本有时候环境的某些配置不一样,也会有影响。
    回复 有任何疑惑可以回复我~ 2019-01-22 11:40:13
大漠风 2019-01-17 22:25:54

你加的`@Transactional`标签,是哪个包里的?

0 回复 有任何疑惑可以回复我~
  • 提问者 qq_慕神9216905 #1
    org.springframework.transaction.annotation.Transactional;
    回复 有任何疑惑可以回复我~ 2019-01-18 09:00:19
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信