Atomikos TransactionsEssentials で JTA (XA with MySQL編)
前回の Atomikos TransactionsEssentials で JTA (Spring + JDBC 編) では、普通に UserTransaction を使ってみたところ、特に問題なく動作しました。
しかし、JPA を使い始めると、どうも動作がおかしい。
null source
まずは、以下のエラー。
Exception in thread "main" java.lang.IllegalArgumentException: null source at java.util.EventObject.<init>(EventObject.java:38) at javax.sql.StatementEvent.<init>(StatementEvent.java:39) at com.mysql.jdbc.jdbc2.optional.JDBC4PreparedStatementWrapper.close(JDBC4PreparedStatementWrapper.java:70) at org.hibernate.jdbc.AbstractBatcher.closePreparedStatement(AbstractBatcher.java:534) at org.hibernate.jdbc.AbstractBatcher.closeStatement(AbstractBatcher.java:269) at org.hibernate.id.insert.AbstractReturningDelegate.releaseStatement(AbstractReturningDelegate.java:58) at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:36) at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2163) at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2643) at org.hibernate.action.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:51) at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:279) at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:298) at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:181) at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:107) at org.hibernate.ejb.event.EJB3PersistEventListener.saveWithGeneratedId(EJB3PersistEventListener.java:49) at org.hibernate.event.def.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:131) at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:87) at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:38) at org.hibernate.impl.SessionImpl.firePersist(SessionImpl.java:618) at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:592) at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:596) at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:220) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:357) at $Proxy9.persist(Unknown Source) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:194) at $Proxy9.persist(Unknown Source) at sample.JpaExample1.main(JpaExample1.java:43)
おいら側のソース的には、以下のように、ただエンティティを persist しているだけです。
em1.persist(a1);
エラー吐いてるクラスは com.mysql.jdbc.jdbc2.optional.JDBC4PreparedStatementWrapper ですね。
ドライバが怪しいかな、、、。
Connector/J のバージョンを 5.1.5, 5.1.4 に落としてみた。
ということで、ドライバのバージョンを、5.1.5, 5.1.4 のように落としながら試してみました。
すると、エラーが NullPointerException に変わりました。
Exception in thread "main" java.lang.NullPointerException at org.hibernate.jdbc.AbstractBatcher.closePreparedStatement(AbstractBatcher.java:534) at org.hibernate.jdbc.AbstractBatcher.closeStatement(AbstractBatcher.java:269) at org.hibernate.id.insert.AbstractReturningDelegate.releaseStatement(AbstractReturningDelegate.java:58) at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:36) at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2163) at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2643) at org.hibernate.action.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:51) at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:279) at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:298) at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:181) at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:107) at org.hibernate.ejb.event.EJB3PersistEventListener.saveWithGeneratedId(EJB3PersistEventListener.java:49) at org.hibernate.event.def.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:131) at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:87) at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:38) at org.hibernate.impl.SessionImpl.firePersist(SessionImpl.java:618) at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:592) at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:596) at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:220) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:357) at $Proxy9.persist(Unknown Source) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:194) at $Proxy9.persist(Unknown Source) at sample.JpaExample1.main(JpaExample1.java:43)
今度は hibernate のレベルでエラーを吐いてます。
エラーの出てる箇所は、以下の ps.close(); のところです。
private void closePreparedStatement(PreparedStatement ps) throws SQLException { try { log.trace("closing statement"); ps.close(); // ここ!! if ( factory.getStatistics().isStatisticsEnabled() ) { factory.getStatisticsImplementor().closeStatement(); } } finally { if ( !releasing ) { // If we are in the process of releasing, no sense // checking for aggressive-release possibility. connectionManager.afterStatement(); } } }
となると、ps の実装返しているヤツが犯人か。
しかも、Connetor/J のバージョンを変えて、PreparedStatement が null になったってことは、、、。
やっぱりドライバが怪しい、、、。
Connector/J のバージョンを 5.1.3 に落としてみた。
懲りずに、バージョンを落としてみましたところ、バージョンを 5.1.3 で動きました。
ヽ( ・∀・)ノ ワーイ
以下、MySQL のログです。
650 Query SET autocommit=0 650 Query XA START 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303134,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d3,0x41544f4d 650 Query insert into A (name) values ('Kuma-chan') 650 Query XA END 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303134,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d31,x41544f4d 650 Query XA PREPARE 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303134,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e74631,0x41544f4d 650 Query XA COMMIT 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303134,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d1,0x41544f4d
ロールバックもしてみましたが、問題なしです。
データソースその1
1075 Query SET autocommit=0 1075 Query XA START 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303134,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d31,0x41544f4d 1075 Query insert into A (name) values ('Kuma-chan') 1075 Query XA END 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303134,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d31,0x41544f4d 1075 Query XA ROLLBACK 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303134,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d31,0x41544f4d
データソースその2
1038 Query SET autocommit=0 1038 Query XA START 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303134,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d32,0x41544f4d 1038 Query insert into A (name) values ('Fellow-kun') 1038 Query XA END 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303134,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d32,0x41544f4d 1038 Query XA ROLLBACK 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303134,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d32,0x41544f4d
しかし、まだまだ爆弾が眠っているような気がする。