2013-08-23 38 views
6

(Immer noch ein bisschen neu zu Frühling)Spring: @Transactional @Scheduled Methode löst Transaction

Ich brauche eine Service-Methode haben, die zur gleichen Zeit ist @Scheduled und @Transactional, so dass ich ein DAO nennen erhalten in es.

Deklarative Transaktionen sind aktiviert, der Transaktionsmanager ist ein org.springframework.orm.hibernate3.HibernateTransactionManager, der auf einer Hibernate-Sitzungsfactory basiert.

Die Serviceklasse implementiert keine Schnittstelle, daher wird ein CGLIB-Proxy verwendet.

Diese Einrichtung funktioniert im Allgemeinen gut (Methoden, die aus dem Web-Stack aufgerufen werden, d. H. Struts), aber diese Methode löst beim Aufruf durch den Scheduler eine Ausnahme aus.

Hier sind die entsprechenden Bits des Codes:

Die Service-Methode (die Klasse ClientWakeAndTerminateManager genannt):

@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 

    } 

Relevante Teile meines Anwendungskontext:

<!-- 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> 

Ausnahmestapel Spur:

[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 

Der Stack-Trace scheint mir zu sagen, dass ein Transaktions-Proxy tatsächlich verwendet wird, so dass ich diese Ausnahme nicht verstehe. Hilfe !

EDIT:

ich durch die @Transactional und die @Scheduled Anmerkungen zu trennen versucht:

  • Erstellen Sie eine neue Klasse/Bean, die die @Scheduled Methode
  • Injizieren Sie meinen Dienst zu dieser Bohne contaisn
  • Entfernt die @Scheduled von meiner ursprünglichen Methode, aber verließ die @Transactional

Aber ich bekomme immer noch die selbe Ausnahme. Ich habe auch versucht, die @Transactional auf meine DAO-Methode zu setzen und sie von meiner Service-Methode zu entfernen: das gleiche Ergebnis.

+0

zurück dies passieren kann, wenn bereits begangen oder rückgängig gemachte Transaktion versucht – wedens

+0

können Sie Ihre dao Methode zeigen, zu begehen oder Rollback? – wedens

+1

OK, meine DAO-Methode war die Schuldige. Ich fing an, es zu vermuten, und dann machte dein Kommentar mich zweimal auf. Die Methode enthielt also einige übriggebliebene manuelle Session-Commits (ich modernisiere diese App kürzlich und "spring" sie aus), als der Transaktions-Proxy Calls anrief, scheiterte es, weil es bereits commited war! Vielen Dank für Ihre Zeit. Wenn Sie Ihre Antwort bearbeiten, um die DAO-Methode zu erwähnen, akzeptiere ich sie. –

Antwort

11

erstellen Sie separate Klasse mit der Methode, die mit @Transactional annotiert ist, und rufen Sie diese Methode in Ihrer @Scheduled annotierten Methode auf. Frühling wird einen Anruf durch Proxy tun und @Transactional richtig handhaben.

EDIT: auch auf Ihre DAO-Methode suchen und stellen Sie sicher, dass es verpflichtet sich, oder rollt Transaktion manuell

+0

Danke, ich habe dies getan, aber ich bekomme den gleichen Fehler (siehe bearbeiten) –

+0

Danke @Wedens für diese Antwort, Seine Arbeit für mich.Kann erklären, warum es nicht funktioniert, wenn Methode in der gleichen Klasse ist. – hayat

+0

Ich weiß, sehr sehr alte Post, aber ich hasse es, die Frage hängen zu lassen. Der Grund ist wegen der Art, wie der Proxy funktioniert. Die einfachste Antwort ist, dass sie sehen kann, was ein- und ausgeht, aber nicht, was im Inneren vorgeht. Dies liegt an der Art eines Proxy. – Wes

Verwandte Themen