0

私はHibernate 5.1でSpring 4.3.8.RELEASEを使用しています。私は、スレッドプールは私のコンテキストでSpring 4では、メインスレッド以外で@Transactionalを作成するにはどうすればよいですか?

<bean id="myprojectThreadFactory" class="org.springframework.scheduling.concurrent.CustomizableThreadFactory"> 
    <constructor-arg value="myproject-"/> 
</bean> 
<bean id="myprojectTaskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"> 
    <property name="threadFactory" ref="myprojectThreadFactory"/> 
    <property name="corePoolSize" value="${myproject.core.thread.pool.size}" /> 
    <property name="maxPoolSize" value="${myproject.max.thread.pool.size}" /> 
</bean> 

を設定している。しかし、どのように私は私のメインスレッドの外にある私のタスク・スレッドの一つの中のトランザクションを作成するのですか?私はこの

 // Cue up threads to execute 
     for (final Organization org : allOrgs) 
     { 
      m_threadExecutor.execute(new Thread(new Runnable(){ 
       @Override 
       @Transactional(propagation=Propagation.REQUIRES_NEW) 
       public void run() 
       { 
        System.out.println("started."); 
        processData(org.getId()); 
        System.out.println("finished."); 
       } 
      })); 

をしようとしているが、これはあなたのRunnableをインスタンスについては何も知らない

Exception in thread "myproject-1" Exception in thread "myproject-2" org.hibernate.SessionException: Session is closed! 
    at org.hibernate.internal.AbstractSessionImpl.errorIfClosed(AbstractSessionImpl.java:132) 
    at org.hibernate.internal.SessionImpl.setCacheMode(SessionImpl.java:1511) 
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:1109) 
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:1033) 
    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:497) 
    at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:298) 
    at com.sun.proxy.$Proxy68.find(Unknown Source) 
    at org.mainco.subco.core.repo.GenericDao.find(GenericDao.java:123) 
    at org.mainco.subco.organization.repo.OrganizationDaoImpl.find(OrganizationDaoImpl.java:61) 
    at org.mainco.subco.organization.service.OrganizationServiceImpl.getDescendantOrganizations(OrganizationServiceImpl.java:283) 
    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:497) 
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) 
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99) 
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282) 
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213) 
    at com.sun.proxy.$Proxy75.getDescendantOrganizations(Unknown Source) 
    at org.mainco.subco.myproject.repo.myprojectClassDaoImpl.findBymyprojectOrg(myprojectClassDaoImpl.java:89) 
    at org.mainco.subco.myproject.service.myprojectClassServiceImpl.find(myprojectClassServiceImpl.java:300) 
    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:497) 
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) 
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99) 
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282) 
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) 
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213) 
    at com.sun.proxy.$Proxy91.find(Unknown Source) 
    at org.mainco.subco.myproject.quartz.ImportClassesWorker.preProcessData(ImportClassesWorker.java:56) 
    at org.mainco.subco.myproject.quartz.AbstractImportDataWorker.processData(AbstractImportDataWorker.java:126) 
    at org.mainco.subco.myproject.quartz.AbstractImportDataWorker.access$0(AbstractImportDataWorker.java:123) 
    at org.mainco.subco.myproject.quartz.AbstractImportDataWorker$1.run(AbstractImportDataWorker.java:110) 
    at java.lang.Thread.run(Thread.java:745) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
    at java.lang.Thread.run(Thread.java:745) 

答えて

0

ロジックにはTransactionTemplateを使用してください。このようなもの

final TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager); 
    taskExecutor.execute(new Runnable() { 
     @Override 
     public void run() { 
      transactionTemplate.execute(new TransactionCallbackWithoutResult() { 
       @Override 
       protected void doInTransactionWithoutResult(TransactionStatus status) { 
       System.out.println("started."); 
       processData(org.getId()); 
       System.out.println("finished."); 
       } 
      }); 
     } 
    }); 
+0

ありがとうございます。 @Serviceメソッドをトランザクションとしてマークし、使用するトランザクションテンプレートを指定する方法はありますか?私は "processData"メソッドが30分以上かかるので、私はそれを単一のトランザクションにしたいとは思いません。それはサービスメソッドを呼び出すので、私はそれらのそれぞれが別個のトランザクションであることを望みます。 – Dave

0

春、以下の例外が生じています。したがって、runメソッドに注釈を追加することは意味をなさない。代わりに、@TransactionalprocessDataメソッドに入力します。しかし、は、Spring beanのメソッドである必要があります。

UPDATE: ちょうど@Transactional@Asyncの両方でビジネスメソッドをマークしようとしましたが、それは私のために働きました。私はバージョン1.5.4のspring-bootを使いました。リリースはspring 4.3.9.RELEASEとhibernate 5.0.12.finalです。 @Asyncの設定では、@EnableAsyncを使用しました。ここに私が持っているもの:

@Test 
@Transactional 
public void test() throws InterruptedException { 
    beanA.testMethodA(); 

    //Sleeping, since after test is completed application is down which leaves @Async transaction not completed. 
    Thread.sleep(3000); 

    System.out.println("Thread in test method: " + Thread.currentThread().getName()); 
    System.out.println("Transaction in test method: " + TransactionSynchronizationManager.getCurrentTransactionName()); 
} 

ここはBeanAの方法です。 - @Async@TransactionalとしてマークされBeanBの方法

@Override 
@Transactional 
public void testMethodA() { 
    beanB.testMethodB(); 

    System.out.println("Thread in method A: " + Thread.currentThread().getName()); 
    System.out.println("Transaction in method A: " + TransactionSynchronizationManager.getCurrentTransactionName()); 
} 

そして最後の部分:それは、テストによって開始されたトランザクションに囲まなり、デフォルトの伝播レベルのトランザクションです。これは、別のスレッドで、別のトランザクションで実行さん:

@Async 
@Transactional 
@Override 
public void testMethodB() { 
    System.out.println("Thread in method B: " + Thread.currentThread().getName()); 
    System.out.println("Transaction in method B: " + TransactionSynchronizationManager.getCurrentTransactionName()); 
} 

私は次の出力を取得し、テスト実行した後:

Thread in test method: main 
Transaction in test method: com.example.stackoverflow.TransactionTest.test 

Thread in method A: main 
Transaction in method A: com.example.stackoverflow.TransactionTest.test 

Thread in method B: SimpleAsyncTaskExecutor-1 
Transaction in method B: com.example.stackoverflow.BeanBImpl.testMethodB 

注最後の二つの文を。 @Async@Transactionalと表示されているメソッドは、独自のトランザクションと独自のスレッドで実行されています。

+0

これは機能しません。 processDataはすでにTransactionalとしてマークされているautowired @Serviceクラスを呼び出しています。先ほど説明した方法で同じエラーが発生していたため、「実行」ブロックの周りにTransactionalを追加しました。 – Dave

+0

うーん..奇妙な... Btw、代わりに非同期@Asyncを使用するより良い方法?それは実現可能ですか?いくつかの情報:http://www.baeldung.com/spring-async –

+0

この場合、この回答に従うことができます:https://stackoverflow.com/questions/29258436/nested-transactional-methods-with-async –

関連する問題