2017-03-07 34 views
2

次のコードが機能しない理由がわかりません。新しいトランザクションをループで開始する(propagation = REQUIRES_NEW)。そして、このトランザクションで新しいトランザクションが発生する前に、すべてのトランザクションをコミットする必要があります。ただし、ループの最初の反復のみが実行され、その後は何も起こりません。ループ内で新しいトランザクション(REQUIRES_NEWを使用)の伝播が期待通りに機能していない

@Service 
    @Transactional 
    public class Aimpl implements A { 

    @Autowired 
    private B b; 

    private Logger logger = LoggerFactory.getLogger(this.getClass()); 

     public void methodA(List<Customer> customers){ 
     logger.info("before loop"); //gets printed 
     customers.forEach(customer -> { 
     logger.info("1"); //--> this gets printed 
     b.processEachCustomer(customer); 
     logger.info("2"); //- this does not get printed 
     }); 
     logger.info("after loop"); //does not get printed 
     } 
    } 

//-----------------Second class---------- 


@Service 
    @Transactional 
    public class Bimpl implements B { 

    @Autowired 
    private MyRepository repository; 

    private Logger logger = LoggerFactory.getLogger(this.getClass()); 

     @Transactional(propagation = Propagation.REQUIRES_NEW) 
     public void processEachCustomer(Customer customer){ 

     //process each customer - a new transaction everytime 
     //and it should be committed independently 
     repository.updateCustomerData(customer.getId()); 
     logger.info("3");//this does not get printed 
     } 
    } 

これは、1つの行のテーブルで更新クエリを発行するリポジトリクラスです。

public interface MyRepository extends Repository<Customer , Long> { 

    @Modifying 
    @Query("UPDATE Customer c SET c.status = 1 WHERE i.id= :id") 
    int setStatusById(@Param("id") Integer id); 

} 

私はここで間違っていますか?基本的に、なぜループの最初の反復のみが動作し、残りは実行されませんか?私はそれをデバッグしようとしており、アプリケーションが最初の反復後にブレークポイントで停止するのを見ません。

+0

「実行がかなり停止する」とはどういう意味ですか? – galovics

+0

最初の反復後に何も起こりません。私はそれをデバッグしようとしており、ブレークポイントで停止することはなく、何も起こっていないことを示すログメッセージはありません。 – Righto

+0

ログメッセージをループの内側とループの前後に置くとどうなりますか?コンソールには何が書かれていますか? – galovics

答えて

0

これは、methodA()からアノテーションを削除し、クラスAimplでクラスレベルのトランザクションアノテーションを削除してもうまくいきました。

@Service 
    public class Aimpl implements A { 

    @Autowired 
    private B b; 

    private Logger logger = LoggerFactory.getLogger(this.getClass()); 

     public void methodA(List<Customer> customers){ 
     customers.forEach(customer -> { 
     b.processEachCustomer(customer); 
     }); 
     } 
    } 

// -----------------セカンドクラス----------

@Service 
@Transactional 
public class Bimpl implements B { 

@Autowired 
private MyRepository repository; 

private Logger logger = LoggerFactory.getLogger(this.getClass()); 

    @Transactional(propagation = Propagation.REQUIRES_NEW) 
    public void processEachCustomer(Customer customer){ 

    //process each customer - a new transaction everytime 
    //and it should be committed independently 
    repository.updateCustomerData(customer.getId()); 
    } 
} 

EDIT 2:私にしてみましょうここで自分を正してください。これは、メソッドからトランザクションアノテーションを削除してもクラスがトランザクションに注釈を付けたままにしてもうまく動作します。実際の問題は、他のプロセスによって取得されたロックのためにデータベースレベルで発生していたデッドロックです。コードはそのままです。

0

メソッドAは、@Transactionalがクラスレベルであるため、デフォルトスコープREQUIREDのトランザクションを作成します。

+0

methodAを更新して@Transactional(propagation = Propagation.REQUIRES_NEW)と注釈を付けても、問題は同じままです – Righto

+0

これは受け入れられた回答ではないはずです。OPはメソッドBが新しいトランザクションを生成することを期待しますこれは発信者のトランザクションには絶対に関係しません(内部トランザクションが実行されている間は外部トランザクションは中断されます)。 – Gab

+0

さて、私は私の答えを受け入れるべきです – Righto

関連する問題