14

(对 Spring 还是有点新意)

我需要同时有一个服务方法@Scheduled@Transactional这样我才能在其中调用一个 DAO。

启用声明式事务,事务管理器是org.springframework.orm.hibernate3.HibernateTransactionManager基于休眠会话工厂的。

服务类不实现任何接口,因此使用了 CGLIB 代理。

此设置通常工作正常(从 Web 堆栈调用的方法,即 Struts),但此方法在由调度程序调用时引发异常。

以下是相关的代码位:

服务方法(类被调用ClientWakeAndTerminateManager):

@Scheduled(initialDelay = 5000, fixedRateString = "${rmi.server.threads.clientsScheduleManagement.rate}")
    @Transactional(readOnly = true)
    public void runCheck(){

        //Call a read-only DAO method (the DAO is @Autowired as a class field)

        //do some stuff with the data loaded from DB

    }

我的应用程序上下文的相关部分:

<!-- switch on the transactional infrastructure -->
    <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>

    <!-- Utility class to execute transactional code where use of annotation is not possible -->
    <bean class="org.springframework.transaction.support.TransactionTemplate" id="txTemplate">
        <constructor-arg name="transactionManager" ref="transactionManager"/>
    </bean>

    <!-- Transaction manager based on Hibernate -->
    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="hibernateSessionFactory"/>
    </bean>

异常堆栈跟踪:

[ERROR] : Unexpected error occurred in scheduled task.
org.springframework.transaction.TransactionSystemException: Could not commit Hibernate transaction; nested exception is org.hibernate.TransactionException: Transaction not successfully started
    at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:661)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:755)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:724)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:475)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:270)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:631)
    at ch.unine.sitel.lis.rmi.shared.ClientWakeAndTerminateManager$$EnhancerByCGLIB$$d8be4f34.runCheck(<generated>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:64)
    at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:53)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
    at java.util.concurrent.FutureTask$Sync.innerRunAndReset(FutureTask.java:351)
    at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:178)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:178)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
    at java.lang.Thread.run(Thread.java:722)
Caused by: org.hibernate.TransactionException: Transaction not successfully started
    at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:127)
    at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:657)
    ... 22 more

堆栈跟踪似乎告诉我确实使用了事务代理,所以我不明白这个异常。帮助 !

编辑:

我试图通过以下方式分隔注释@Transactional@Scheduled注释:

  • @Scheduled创建一个包含该方法的新类/bean
  • 将我的服务注入到这个 bean
  • 从我原来的方法中删除了@Scheduled,但留下了@Transactional

但我仍然得到同样的例外。我还尝试将其@Transactional放在我的 DAO 方法上并将其从我的服务方法中删除:结果相同。

4

2 回答 2

29

使用带注释的方法创建单独的类,@Transactional并在带注释的方法中调用此@Scheduled方法。spring 将通过代理进行调用并@Transactional正确处理。

编辑:还要查看您的 DAO 方法并确保它不会手动提交或回滚事务

于 2013-08-23T11:27:59.057 回答
1

就我而言

@EnableTransactionManagement

没有使用。在我将此注释添加到我的 @Configuration 类之一后,它开始工作。

于 2018-12-13T11:26:01.707 回答