2013-04-27 2 views
5

のは、我々は次のコードがあるとしましょう:新しいトランザクションは、以前のすべてのエンティティをデタッチしますか?

@Entity 
public class User { 
    @Id 
    private String name; 
    @OneToOne(cascade = CascadeType.ALL) 
    private Address address; 
    //getters and setters 
} 

@Entity 
public class Address { 
    @Id 
    private int id; 
    private String street; 
    //getters and setters 
} 

@Stateless 
//@Service 
public class UserLogicClass { 
    @PersistenceContext 
    //@Autowired 
    private EntityManager entityManager; 

    public void logicOnUser(User user) { 
     if(logicOnAddress(user.getAddress()) { 
      otherLogicOnUser(user); 
     } 
    } 

    public boolean logicOnAddress(Address address) { 
     // 
     entityManager.find(address);//address becomes managed 
     // 
    } 

    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) 
    //@Transactional(propagation = Propagation.REQUIRES_NEW) 
    public void otherLogicOnUser 
    // 
     entityManager.find(user);/*without annotation, user is not managed and address is managed, but with the transaction annotation is the address still managed?*/ 
    // 
    } 
} 

質問が最後のメソッドからのコメントに依存しています。私は、Springの場合とEJBの場合の両方で何が起こっているのかを調べています。 SpringがJTAトランザクションで構成され、このクラスから呼び出されたすべてのメソッドがEJBと同じように新しいトランザクションを開始すると仮定します。

答えて

5

それはもっとJPAの問題です。 JPA 2.0仕様から

@PersistenceContext(type = PersistenceContextType.EXTENDED) 
//@Autowired 
private EntityManager entityManager; 

引用::コンテナ管理の永続コンテキストを定義することができる

が持っているいずれかの 一生あなたはそれを拡張しますしない限り、EntityManagerのは、新しいトランザクションに伝播されませんそのエンティティマネージャーが であるときに指定された PersistenceContextTypeに応じて、単一のトランザクションにスコープされているか、複数のトランザクションにまたがる拡張された の存続期間になります。この仕様は、 トランザクションスコープの永続コンテキストと拡張永続コンテキスト のような永続コンテキストをそれぞれ指します。

+0

だから、タイプが拡張に設定されていない限り、そのメソッドの内部で、新しいエンティティマネージャは、任意の管理対象エンティティを持たない、作成されましたか? – m3th0dman

+1

はい、正確です。 'otherLogicOnUser'メソッドでは、新しいトランザクションが作成され、永続コンテキストを拡張させない限り、永続コンテキストを伝播してはいけません。 – dcernahoschi

+0

拡張EntityManagerの使用はステートフルEJBで使用するように設計されており、スレッドセーフではなく、トランザクションスコープのEntityManagerを使用するメソッドが同じトランザクション内の拡張EntityManagerを使用するメソッドを呼び出すと、永続コンテキストの衝突が発生する可能性があります。 – German

5

注:このメカニズムは、プロキシに基づいているので、プロキシを介して入ってくるコール のみ「外部」法が傍受されるであろう。これは、 'self-invocation'、つまりターゲットオブジェクト内のメソッド 他のメソッドを呼び出しても、呼び出されたメソッドが@Transactionalでマークされていても、実行時に実際のトランザクション につながることはありません。

otherLogicOnUser()がターゲットオブジェクト内で呼び出されます。

続きを読む:EJB Transactions in local method-calls