2016-06-16 7 views
0

UPD 1:JPA:ネストされたトランザクションの方法はロールバックされません

  • 私はWildFly 9.0.2にJNDIルックアップを通じてデータソースを取得し、その後、「ラップ:私は、以下の情報が役に立つかもしれないと思うさらなる研究の際それは例えばHikariDataSource(例えば、return new HikariDataSource(jndiDSLookup(dsName)))に入ります。
  • 最終的に使用されるトランザクションマネージャはJTATransactionManagerです。
  • 私はトランザクションマネージャを設定しません。

元の質問:

私はJPA/HibernateとDBの変更が別のクラスのトランザクションメソッドから呼び出された一つのクラスのトランザクションの方法で導入された(多分)春ブートで問題が発生しています呼び出し元メソッドの変更がロールバックされていても(コミットされるはずです)、コミットされます。ここで

は私のトランザクションサービスは

StuffServiceです:

@Service 
@Transactional(rollbackFor = IOException.class) 
public class StuffService { 

    @Inject private BarService barService; 
    @Inject private StuffRepository stuffRepository; 

    public Stuff updateStuff(Stuff stuff) { 

     try { 
      if (null != barService.doBar(stuff)) { 
       stuff.setSomething(SOMETHING); 
       stuff.setSomethingElse(SOMETHING_ELSE); 
       return stuffRepository.save(stuff); 
      } 
     } catch (FirstCustomException e) { 
      logger.error("Blah", e); 
      throw new SecondCustomException(e.getMessage()); 
     } 

     throw new SecondCustomException("Blah 2"); 
    } 

    // other methods 
} 

BarService

@Service 
@Transactional 
public class BarService { 

    @Inject private EntityARepository entityARepository; 
    @Inject private EntityBRepository entityBRepository; 

    /* 
    * updates existing entity A and persists new entity B. 
    */ 
    public EntityA doBar(Stuff stuff) throws FirstCustomException { 

     EntityA a = entityARepository.findOne(/* some criteria */); 
     a.setSomething(SOMETHING); 

     EntityB b = new EntityB(); 
     b.setSomething(SOMETHING); 
     b.setSomethingElse(SOMETHING_ELSE); 

     entityBRepository.save(b); 
     return entityARepository.save(a); 
    } 

// other methods 
} 

EntityARepositoryEntityBRepositoryは、次のように定義された非常によく似春ブーツのリポジトリです:

public interface EntityARepository extends JpaRepository<EntityA, Long>{ 

    EntityA findOne(/* some criteria */); 
} 

FirstCustomExceptionThrowable

SecondCustomExceptionを拡張延びRuntimeException

Stuffエンティティがバージョン管理され、そしてすべてのたまにそれを同時にStuffService.updateStuff()によって更新されます。その場合、stuffインスタンスの1つへの変更は、予想どおりにロールバックされますが、barService.doBar()で発生したすべてがコミットされます。

両方のメソッドでのトランザクションの伝達がREQUIRED(デフォルトのもの)で、両方のメソッドが異なるクラスに属しているので、これは非常に困惑します。したがって、@Transactionalを両方に適用する必要があります。

私はTransaction is not completely rolled back after server throws OptimisticLockException1

を見やった。しかし、それは本当に私の質問に答えませんでした。

誰でも私に何が起こっているのか考えてもらえますか?

ありがとうございます。

+0

サービスのいずれかでロールバックが発生するエラー/例外はありますか。 – Mubin

+0

@Mubin: 'OptimisticLockException'は' StaleObjectStateException'によってかなり予想通りに引き起こされます。 – kooker

答えて

0

これは「ネスト」トランザクションではありません。これらのサービスは完全に独立したトランザクションで動作しています。一方のロールバックが他方のロールバックに影響を与えるようにするには、自分自身を開始するのではなく、同じトランザクションに参加させる必要があります。

また、doBarメソッドに渡された 'stuff'のバージョンに問題があり、検証する必要がある場合は、オプティミスティックロックチェックの原因となるstuffインスタンスを使用する必要があります。古くなった場合は例外が発生します。 EntityManager.lock

+0

こんにちは@クリス、答えに感謝します。私は 'REQUIRED'伝播レベルで' barService.doBar() 'が' Stuff Service.updateStuff() 'によって開始されたトランザクションに参加すると考えました。なぜあなたはそれらが別々のトランザクションに関連付けられていると思いますか? – kooker

+0

はい、必須です。トランザクションでラップする必要があります。あなたの呼び出しメソッドはそのトランザクションを制御していますか、または非トランザクションであり、これらの別々の呼び出しごとにトランザクションを開始/コミットすることはできませんか? – Chris

+0

これは、別のトランザクションメソッドを呼び出す1つのトランザクションメソッドです。呼び出されたメソッドは呼び出し元メソッドによって開始された同じトランザクションに参加することになっているので、両方をロールバックする必要があります。しかし、今の場合はそうではありません。呼び出し側メソッドに例外がある場合、そのメソッドだけがロールバックされます。 – kooker

関連する問題