2012-02-03 9 views
5

JBoss 7を使用するSeam 3サンドボックスアプリケーション、デフォルトJPA実装としてHibernate、WebフロントエンドとしてJSFとして使用しています。JPA/HibernateはEJB/Seam環境でコミット時にUPDATEを発行しません

私は、SQL UPDATEがデフォルトでは飲み込まれるという問題があります。対話スコープで

私のステートフルEJBは、拡張がEntityManagerの一つのエンティティは、コンテナ管理のトランザクションは、EntityManagerのは、EJBエンティティをロードするためにEMを使用し続ける

  • を注入します

    1. (新しい必要です)スコープを維持しますその場で
    2. JSFアプリケーションはEJBとそのエンティティにアクセスし、文字列フィールドを変更
    3. JSFアプリケーションは、EJB
    4. に「保存」方法をcalles
    5. でsave()エンティティフィールドが変更されているかどうかチェックします。>正しく変更された場合
    6. save()が完了した後、コンテナはトランザクションをコミットします。
    7. 問題:DBに対してSQL更新が実行されません。

    iを)(保存拡張する場合:

    予想通りA)entityManager.contains(エンティティ)はUPDATEが実行される(結果が "真" である)

    OR

    B) entityManager.persist(entity)UPDATEが期待どおりに実行される

    Q:エンティティがプロセス全体で管理されているため、仕様の理解が必要な場合は、a)またはb)のどちらも必須ではありません。 私は理解しません、なぜa)節約に影響します。 私はイメージングすることができますb)節約に効果がありますが、それは必須ではありませんか?

    説明を歓迎します。ここで

    は私のEJBです:

    @Named 
    @ConversationScoped 
    @Stateful 
    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) 
    public class LanguageBean { 
    
        @PersistenceContext(type = PersistenceContextType.EXTENDED) 
        private EntityManager em; 
        @Inject 
        private UserTransaction transaction; 
    
        private Language value; 
    
        @Inject 
        Conversation conversation; 
    
        public LanguageBean() { 
         super(); 
        } 
    
        @Begin 
        public void selectLanguage(Long anId) { 
         conversation.setTimeout(10 * 60 * 1000); 
         if (anId != null) { 
          value = em.find(Language.class, anId); 
         } 
        } 
    
        @BeforeCompletion 
        public void transactionComplete(){ 
         System.out.println("transactionComplete"); 
        } 
    
        public Language getValue() { 
         return value; 
        } 
    
        @Produces 
        @Named 
        @ConversationScoped 
        public Language getLanguage() { 
         return getValue(); 
        } 
    
        public void setValue(Language aValue) { 
         value = aValue; 
        } 
    
        @End 
        public String save() { 
    //  displays the changed attribute: 
         System.out.println("save code: "+value.getCode()); 
    
    //  why is either this required: 
    //  boolean tempContains = em.contains(value); 
    //  System.out.println("managed: "+tempContains); 
    
    //  or: why is persist required: 
         em.persist(value); 
         return "languages?faces-redirect=true"; 
        } 
    
        @End 
        public String cancel() throws SystemException { 
         transaction.setRollbackOnly(); 
         return "languages?faces-redirect=true"; 
        } 
    
    } 
    
  • +0

    私はentityManager.flushを発見()も問題を解決します。しかし、なぜこれが必要と思われるのか分かりません。 JPAの仕様から: "JTAトランザクションがコミットするとき、プロバイダはすべての変更されたエンティティ状態を データベースにフラッシュする必要があります。" – user1187037

    +0

    多分、休止状態のセッションのFlushModeがnoneに設定されているかもしれませんか? – Firo

    答えて

    0

    @Endで注釈を付けた方法で@Remove注釈を追加してください。

    私の意見では、@End注釈はBeanの破壊にはなりません。したがって、永続コンテキストはsave()の実行後でもアクティブであり、その内容はデータベースにフラッシュできません。

    1

    私の経験は主にseam-2ですが、ここでも同じように適用する必要があります。

    カンバセーションとJPAセッションは、会話の終了によってエンティティが保存されないという単純な理由のために、継ぎ目で切り離されます。例えば

    (もう会話を維持する理由はないので)、実行時間の長い会話のキャンセルアクションは、会話を終了することになる

    あなたはあなたの例では、キャンセルのロールバックを行っていることを考えると、 @ user1187037(理論的にコミットが許可されているとは思えないが)と思われるようにフラッシュを呼び出す必要があると論理的に思えるだろう。

    私はそれがフラッシュしたように設定できるかもしれないと思う私は間違っているかもしれません。いずれの場合においても

    http://javalangblog.blogspot.co.uk/2010/04/flush-mode-conversation.htmlは解決に役立ちます

    希望を示唆しているようです。

    EDIT:あなたは、XML

    <begin-conversation join="true" flush-mode="COMMIT" /> 
    

    との会話は、それが明示的に定義されずに@Endができることをしかし心の中で注釈

    @Begin(flushMode=COMMIT) 
    

    ベアを使用してを使用して、会話ごとにフラッシュモードを設定することができます。ユーザーが会話を途中で終了し、エンティティを変更してから会話を放棄すると、タイムアウト後に自動的に閉じられます。私が正しく覚えていれば、上記の場合に変更がコミットされます。

    参考文献:

    http://docs.jboss.org/seam/3/persistence/3.0.0.Alpha1/reference/en-US/html_single/#d0e249 http://docs.jboss.org/seam/3/latest/api/org/jboss/seam/persistence/FlushModeType.html