Sybaseの件。続き。
結局の所、そんなに凄いものを作らなくても、何故か動くようになる様なので、
処理をアスペクトとして切出してみます。
package org.seasar.extension.tx; import javax.transaction.Transaction; import javax.transaction.TransactionManager; import org.aopalliance.intercept.MethodInvocation; /** * @author taichi S. */ public class NotSupportedInterceptor extends AbstractTxInterceptor { public NotSupportedInterceptor(TransactionManager transactionManager) { super(transactionManager); } public Object invoke(MethodInvocation invocation) throws Throwable { Transaction tx = null; if (hasTransaction()) { tx = suspend(); } try { return invocation.proceed(); } finally { if (tx != null) { resume(tx); } } } }
んで、dao.diconを修正します。
動かしてみます………。サックリと動作します。
と言う訳で、場当たり的な対応ですが、SybaseでS2DAOを使う時には、
DaoMetaDataFactoryImplにNotSupportedInterceptorを適用すれば良い…
と言う事になるようです……。
これで、何故大丈夫なのか、きちんと説明出来ないのが何とも情け無いです。
感覚的には…、
DatabaseMetaDataを取りに行く前に、トランザクションをsuspendする事で、
JDBCのAPI越しに、暗黙的に発行されるクエリに対して暗黙的なトランザクションが発生する。
その為、Sybaseが内部的にCREATE TABLE したり、メタデータを取る為のクエリを発行したりしていても、
それぞれ別なトランザクションの中にあるステートメントとして処理され、
それぞれコミットされる為、例外が発生しないようになる。
かなぁ……と思うのですが、現象面では、
CREATE TABLEの結果が残ったり残らなかったりしているので、
この説明では不十分…と言うことになります。
謎は、
- Sybaseは、何故メタデータを取ろうとしてる対象のテーブルをtempdbにCREATE TABLE するのか?
- そもそも一時表なら、当該テーブルに対するSELECT文が発行された時に、作成されるのでは無いのか?
- 何故、 'ddl in tran', trueとfalseで、処理の結果としてtempdbにテーブルが残ったり残らなかったりするのか?
最終的には、この対応で果たして、大丈夫なのか裏が欲しいです。
それから、他に何か問題が起こる可能性は無いのか、知りたいです。
単純に考えると、以下の様な問題が起こり易くなるんじゃないかなぁ…と思います。
これから、NotSupportedInterceptorをリリースするべくきちんとテストをします。