2017-08-23 2 views
1

私はJBoss/Wildfly 7.1のJava Persistence APIを使用してMSSQLデータベースと通信しています。私は定期的にテーブルに挿入し、更新する長い実行非同期関数を持っているが、各更新の間に数秒間あります。この関数が実行されている間、テーブルはトランザクション内でロックされ、Javaアプリケーションの内部または外部からテーブルをクエリできません。私はこれを行うと、マージが実行されることはありませんasyncメソッドからem.mergeを繰り返し呼び出すと、データベーステーブルがロックされます

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) 
public void mergeEntity(Entity e){ 
    em.merge(e); 
} 

と:私もmergeEntity方法のための新しいトランザクションを要求しようとした

@Stateless 
class Dao { 

    @PersistenceContext(unitName = "persistenceUnit") 
    private EntityManager em; 

    public void mergeEntity(Entity e){ 
     em.merge(e); 
    } 

    public Entity getEntity(int id){ 
     return em.find(Entity.class,id); 
    } 
} 

class Service { 

    @Inject 
    private Dao dao; 

    private void updateEntity(int id){ 
     Entity e = dao.getEntity(id) 
     //do update logic 
     dao.mergeEntity(e); 
    } 
} 

:以下は、私は私のDAOを実装しています方法の例です操作はちょうどハングアップします。 Hibernateのトレースロギングをオンにしても、問題を示すものは表示されませんでした。積極的にテーブルを変更していないときにHibernateがテーブルをロックするのを防ぐためにできることはありますか?

+0

「スタック」と正確な場所を調べるためにスレッドダンプを取得し、SQLログオンを有効にすると、ロックを引き起こす可能性のあるものが表示されます。 – Chris

答えて

0

。 @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)を入れると、他のトランザクションは決して閉じられませんでした。したがって、マージは新しいトランザクションを開くことができませんでした。 getEntityメソッドに@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)を設定することで、その接続が呼び出されたときにトランザクション内では考慮されません。このようにしてマージメソッドが呼び出されると、コンテナはマージのためだけに新しいトランザクションを自由に開くことができます。

0

MySQL(REPEATABLE_READを使用)以外にも、ほとんどのリレーショナルデータベースシステムのデフォルトの分離レベルはREAD_COMMITTEDです。すべてのデータベースで、デフォルトのトランザクション分離レベルを設定できます。

長時間実行される更新の問題を回避するには、READ_UNCOMMITTEDを試すことができます。 Hibernateで、それは設定を意味します

サービスは包括的なEJBに注入しますので、トランザクションはgetEntity呼び出しからオープン滞在していたように見えます
<property name="hibernate.connection.isolation">1</property> 
関連する問題