Wildflyで2つのデータソースでJPA使ったトランザクション
試したみたことのメモ。
試したこと
Wildflyで、同一のDBを指す、名前以外は同じの2つのデータソースを定義する。
JPA用にそれぞれのpersistence-unitを定義。
1つのEJB処理の中で2つのpersistence-unitに対して操作を行うとどうなるか?
試した理由
物理的には見ているリソースが同じでも、データソース違うからXAじゃないとダメなの?を確認するため。
試したソース
こんな感じの処理。
@PersistenceContext(unitName = "primary") private EntityManager primary; @PersistenceContext(unitName = "secondary") private EntityManager secondary; public void register(Emp emp) { System.out.println(emp); Emp primaryCurrentEmp = primary.find(Emp.class, emp.getId()); if (primaryCurrentEmp == null) { primary.persist(emp); } else { primaryCurrentEmp.setName(emp.getName()); } Emp secondaryCurrentEmp = secondary.find(Emp.class, emp.getId()); if (secondaryCurrentEmp == null) { secondary.persist(emp); } else { secondaryCurrentEmp.setName("secondary"); } }
結果その1
起動はできたけど、実行したらsecondary.findのところでエラーになった。
Caused by: javax.transaction.SystemException: IJ000356: Failed to enlist: java.lang.Throwable: Unabled to enlist resource, see the previous warnings. tx=TransactionImple < ac, BasicAction: 0:ffffc0a83801:387ef9b6:54df6971:9 status: ActionStatus.ABORT_ONLY > at org.jboss.jca.core.connectionmanager.listener.TxConnectionListener$TransactionSynchronization.checkEnlisted(TxConnectionListener.java:848)
どうやら、Arjuna(トランザクションサービス)がデフォルトだと異なるデータソースの同一トランザクション使用をサポートしていないっぽい。
失敗。
結果その2
調べると、システムプロパティで無理やりできるっぽいので下をstandalone.xmlに追記する。
<system-properties> <property name="com.arjuna.ats.jta.allowMultipleLastResources" value="true" /> </system-properties>
結果、メソッドはちゃんと抜けた。
でも、update文が走ったのを最後に処理が止まった。デッドロックした?
DB見ると確かにロック状態になってるのがいる。ので、無理やり解除してエラーで落とす。
これも失敗。
結論
データソース違う場合はXAにすべきっぽい。
番外
データソース同じでpersistence-unitが違う、というのをやってみた。
こっちは大丈夫っぽい。