2

Java SE 7 を使用してデスクトップ アプリケーションに取り組んでいます。アプリケーションは複数のスレッドを使用し、作成された各スレッドに DAO クラスを挿入してデータベースにアクセスします。永続層として、EclipseLink と JPA を使用しています。EntityManager は、コンストラクター注入を使用して DAO クラスに注入されます。これはスレッド セーフではないため、次のようにプロバイダーを使用するアプローチを採用しました。

public PluginInstanceJpaController implements IPluginInstanceDao {

    private EntityManager em;

    @Injected
    public PluginInstanceJpaController(Provider<EntityManager> emp) {
        this.em = emp.get();
    }

    @Transactional 
    public void create(PluginInstance foo) throws Exception {
        em.persist(foo);
    }
}

ただし、まったく同じ EntityManager インスタンスが各 DAO に注入されます。それをセットアップするために、私は Guice によって提供される JpaPersistModule を使用しました。これまでのところ、私のセットアップにはシングルトンがないと確信しています。

注入時に EntityManager の新しいインスタンスを作成するように Guice に指示する方法を知っている人はいますか?

別のアプローチでは、EntityManagerFactory と EntityManager のカスタム プロバイダーを試し、JpaPersistModule を私のビジネスから除外しました。これにより、DAO ごとに EntityManager インスタンスが生成されましたが、@Transactional アノテーション付きメソッドは傍受されませんでした。

この問題の解決策をいただければ幸いです。これまでありがとう!

- - 編集 - -

DAO クラスは、それらを使用している Runnable に注入されます。Runnable はプロバイダーを通じても提供されます。私のモジュール構成は次のようになります。

public class RepositoryModule extends AbstractModule {

    @Override
    protected void configure() {

        // DAO bindings
        bind(IObjectStoreDao.class).to(ObjectStoreJpaController.class);
        bind(IPluginInstanceDao.class).to(PluginInstanceJpaController.class);
    }

    @Provides
    public PluginMonitor newMonitor(IPluginInstanceDao plugDao, IObjectStoreDao osDao) {
        PluginMonitor m = new PluginMonitor();
        m.setPluginInstanceDao(plugDao);
        m.setObjectStoreDao(osDao);
        return m;
    }
}

ここで PluginMonitor は私の Runnable です。インジェクター自体はメインスレッドで作成されます...これが問題だったのでしょうか?

4

2 に答える 2

0

私はJPAに精通していませんが、うまくいけば私はまだ助けることができます:-)

EntityManagerProviderのソースを見ると、がありますThreadLocal<EntityManager>。したがって、デフォルトでは、各スレッドに独自のが必要EntityManagerです。それは私に問題が他の場所にあると信じさせる。EntityManagerをシングルトンに設定しているモジュールがないことを確認しますか?EntityManagerすべてのが同じオブジェクトであるとどのように判断していますか?各DAOは間違いなく独自のスレッドにありますか?モジュールでFooDaoがどのように構成されているか、および各スレッドに新しいFooDaoがどのように提供されているかについて詳しく教えてください。

また、コンストラクターを次のように記述しても問題ありません。

@Inject
public FooDao(EntityManager emp) {
    this.em = emp;
}

Guiceは、インスタンスをEntityManagerProvider提供することを決定する魔法を実行し、インスタンスをEntityManager呼び出してコンストラクターに与えるものを取得します。get()EntityManagerProviderEntityManager

于 2012-08-26T18:10:27.233 に答える