无法提交JPA事务 – RollbackException:事务标记为rollbackOnly

首先,我想说我已经在我的案例中看到了stackoverflow的所有主题,但无论如何都无法解决我的问题。

我需要每晚运行预定的任务来检查任务完成的天气 – 我这样做:

@Service @Transactional public class CronBackGroundProcess { @Autowired private CronJobService cronJobService; @Scheduled(cron = "15 01 01 ? * *") public void StartNightJob() { CronJobLog log = new CronJobLog(); int count = 0; try { log.setStartTime(new Date()); log.setStatus("Entered StartNightJob Function"); cronJobService.saveCronJobLog(log); List Tasks = cronJobService.getActive_AND_InArreasTasks(); log.setStatus("Grabbed List of tasks to Check"); cronJobService.saveCronJobLog(log); for (Task Task : Tasks) { cronJobService.StartNightJobProcess(Task, true); count++; } } catch (Exception e) { CronJobLog log2 = new CronJobLog(); log2.setStatus("Error Occurred " + new Date().toString() + e.getMessage()); cronJobService.saveCronJobLog(log2); } log.setLoansChecked(count); log.setStatus("Finished"); log.setEndDate(new Date()); cronJobService.saveCronJobLog(log); } } 

CronJobService本身是@Transactional并自动连接几个@Transactional服务

 @Service @Transactional public class CronJobService { @Autowired private ProductService productService; @Autowired private RepaymentService repaymentService; @Autowired private CronJobLogDAO cronJobLogDAO; @Autowired private TransferService transferService; public String StartNightJobProcess(Account account, boolean makeTransfers) { do something.... } } } 

该过程没有错误,当所有事务必须提交时,我收到这样的错误:

  org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Transaction marked as rollbackOnly at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:524) ~[spring-orm-4.0.0.RELEASE.jar:4.0.0.RELEASE] at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:757) ~[spring-tx-4.0.0.RELEASE.jar:4.0.0.RELEASE] at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:726) ~[spring-tx-4.0.0.RELEASE.jar:4.0.0.RELEASE] at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:478) ~[spring-tx-4.0.0.RELEASE.jar:4.0.0.RELEASE] at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:272) ~[spring-tx-4.0.0.RELEASE.jar:4.0.0.RELEASE] at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95) ~[spring-tx-4.0.0.RELEASE.jar:4.0.0.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.0.0.RELEASE.jar:4.0.0.RELEASE] at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:646) ~[spring-aop-4.0.0.RELEASE.jar:4.0.0.RELEASE] at ge.shemo.services.core.CronBackGroundProcess$$EnhancerByCGLIB$$30cdcf31.StartNightJob() ~[spring-core-4.0.0.RELEASE.jar:na] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.7.0_79] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) ~[na:1.7.0_79] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.7.0_79] at java.lang.reflect.Method.invoke(Method.java:606) ~[na:1.7.0_79] at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:65) ~[spring-context-4.0.0.RELEASE.jar:4.0.0.RELEASE] at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) ~[spring-context-4.0.0.RELEASE.jar:4.0.0.RELEASE] at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:81) [spring-context-4.0.0.RELEASE.jar:4.0.0.RELEASE] at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) [na:1.7.0_79] at java.util.concurrent.FutureTask.run(FutureTask.java:262) [na:1.7.0_79] at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:178) [na:1.7.0_79] at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:292) [na:1.7.0_79] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [na:1.7.0_79] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [na:1.7.0_79] at java.lang.Thread.run(Thread.java:745) [na:1.7.0_79] Caused by: javax.persistence.RollbackException: Transaction marked as rollbackOnly at org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:58) ~[hibernate-entitymanager-5.0.1.Final.jar:5.0.1.Final] at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:515) ~[spring-orm-4.0.0.RELEASE.jar:4.0.0.RELEASE] ... 22 common frames omitted 

我无法弄清楚为什么。 此外,如果我从@Controller启动相同的function,它工作正常

 @Controller @RequestMapping("/test") public class test { @Autowired private ClientService clientService; @Autowired private CronBackGroundProcess cronBackGroundProcess; @RequestMapping(value = "/test") @ResponseBody public void test() throws Exception { try { cronBackGroundProcess.StartNightJob(); } catch (Exception e) { String s = "sd"; } } } 

所以我的问题是为什么这个函数可以从控制器中运行 – 按预期提交所有内容而不是按计划任务工作(通过所有进程而没有错误)?

如果可以的话,在org.springframework.transaction.interceptor.TransactionAspectSupport.completeTra‌​nsactionAfterThrowing(TransactionInfo txInfo, Throwable ex)放置一个调试断点,然后看看实际的exception是什么。

您不需要将CronBackGroundProcess标记为@Transactional因为在StartNightJob()方法中您无法访问db对DB的所有访问权限,因为我猜您在CronJobService执行。

所以从CronBackGroundProcess删除@Transactional它必须有所帮助。