MySQLデータベースとPostgresデータベースの両方に同じエンティティを永続化しようとしています(これは主に、不整合を特定し、デュアルライトを実行する際の問題の詳細を解明するためです-ここで遭遇しました)。私が見つけた記事にはすべて、追加のフレームワークに依存するソリューションが記載されています。 Glassfish4.0をすぐに使用できるJPA2.1とEclipseLink2.5をJPAプロバイダーとして使用して、これを解決しようとしています。私はEclipseを使用していますが、IDEはpersistence.xmlファイルでの複数の永続性ユニットの構成をサポートしていないため、そのためのXMLを直接記述しています。
私は(同じ方法で)コードでこのようなことをすることを期待していました:
@PersistenceContext(name = "MyAppMySQLPU")
EntityManager emMySQL;
@PersistenceContext(name = "MyAppPostgresPU")
EntityManager emPostgres;
//...etc...
MyThing thing = new MyThing();
//...etc...
emMySQL.persist(thing);
emPostgres.persist(thing);
そして、これを含むpersistence.xml
ファイルを使用します。
<persistence-unit name="MyAppPostgresPU">
<jta-data-source>jdbc/PostgresPool_test</jta-data-source>
<class>model.MyThing</class>
</persistence-unit>
<persistence-unit name="MyAppMySQLPU">
<jta-data-source>jdbc/MySQLPool_test</jta-data-source>
<class>model.MyThing</class>
</persistence-unit>
これを行うと、次のエラーが発生します。
SEVERE: Exception while invoking class org.glassfish.persistence.jpa.JPADeployer prepare method
SEVERE: Exception while preparing the app
SEVERE: Exception while preparing the app : Could not resolve a persistence unit corresponding to the persistence-context-ref-name [MyAppPostgresPU] in the scope of the module called [MyApp]. Please verify your application.
しかし、<persistence-unit>
フレーズの1つだけを含めると(どちらでもかまいません)、エンティティは関連付けられたデータベースに永続化されます-両方で動作させる方法がわかりません同時に(追加のフレームワークで永続性機能を活用せずに)。
動作しました。いくつかのことをしなければなりませんでした。これの重要な部分は、私が取ったアプローチで複数のデータベースを使用するために、分散トランザクションを使用するように接続プールタイプを設定する必要があることです。これは本質的に実験であるため、両方のデータベースが同じトランザクションに存在する必要はありませんでしたが、そのようになっていることは問題ではありません。 ( This 記事は、エラーメッセージからそれを識別するのに役立ちました)。準備されたトランザクションを有効にするには、説明されているようにPostgresパラメーターを変更する必要もありました ここ 。
これですべてがうまくいきました:
(1)Glassfishの場合:
JDBC接続プールで、両方のデータベースのリソースタイプを_javax.sql.XADataSource
_に変更します。 Postgresのデータソースクラス名を_org.postgresql.xa.PGXADataSource
_に変更します。 MySQLのデータソースクラス名を_com.mysql.jdbc.jdbc2.optional.MysqlXADataSource
_に変更します。
(2)Posgres構成の場合(_postgresql.config
_):
_max_prepared_transactions
_を有効にし、_max_connections
_より1大きい値に設定します。 (使用可能なすべての共有メモリを吹き飛ばさないものを見つけるために、両方のパラメータを試してみる必要がありましたが、これは単なる実験であるため、db接続の数を減らすか共有メモリを増やすかは問題ありません)
(3)コード内:@PersistenceContext(name="...")
を@PersistenceContext(unitName="...")
に変更します
この「答え」に関する警告-これのほとんどは私にとって新しいものなので、これはこれを処理するための最もエレガントな方法ではないかもしれません。誰かがこれを解決するための「ベストプラクティス」を提供できれば、私は非常に知りたいと思います。