Sybaseでの、動きがイマイチかもしれない件について

SybaseS2DAOの間に何やら問題があるっぽいです。
正直に言って、この話を聞くまで、
プロダクトを知ってる程度だったので、全容が掴みきれていません。


どんな些細な事でも、構いません。情報のある方、トラックバックかコメントを下さい。
よろしくお願いします。


後、ずらずらと並べている事に間違いがあれば、是非ご指摘下さい。

現象について

Service AdministratorでDBに接続して、トランザクション内でS2DAOを動かすと以下のエラーが発生する。

DEBUG 2005-04-26 00:06:12,250 [main] トランザクションを開始しました
DEBUG 2005-04-26 00:06:13,140 [main] 物理的なコネクションを取得しました
DEBUG 2005-04-26 00:06:13,171 [main] 論理的なコネクションを取得しました
DEBUG 2005-04-26 00:06:13,359 [main] トランザクションロールバックしました
DEBUG 2005-04-26 00:06:13,437 [main] 物理的なコネクションを閉じました
org.seasar.framework.exception.SQLRuntimeException: [ESSR0071]SQLで例外が発生しました。
理由はcom.sybase.jdbc3.jdbc.SybSQLException: 
The 'CREATE TABLE' command is not allowed within a multi-statement transaction in the 'tempdb' database.

  at org.seasar.framework.util.DatabaseMetaDataUtil.addPrimaryKeys(DatabaseMetaDataUtil.java:59)
  at org.seasar.framework.util.DatabaseMetaDataUtil.getPrimaryKeySet(DatabaseMetaDataUtil.java:37)
  at org.seasar.dao.impl.BeanMetaDataImpl.setupPrimaryKey(BeanMetaDataImpl.java:307)
  at org.seasar.dao.impl.BeanMetaDataImpl.setupDatabaseMetaData(BeanMetaDataImpl.java:300)
  at org.seasar.dao.impl.BeanMetaDataImpl.(BeanMetaDataImpl.java:67)
  at org.seasar.dao.impl.BeanMetaDataImpl.(BeanMetaDataImpl.java:54)
  at org.seasar.dao.impl.DaoMetaDataImpl.(DaoMetaDataImpl.java:89)
  at org.seasar.dao.impl.DaoMetaDataFactoryImpl.getDaoMetaData(DaoMetaDataFactoryImpl.java:42)
  at org.seasar.dao.interceptors.S2DaoInterceptor.invoke(S2DaoInterceptor.java:36)
  at examples.dao.DepartmentDao$$EnhancedByS2AOP$$134e4fb$$MethodInvocation$$insert1.proceed(MethodInvocationClassGenerator.java)
  at org.seasar.extension.tx.RequiredInterceptor.invoke(RequiredInterceptor.java:25)
  at examples.dao.DepartmentDao$$EnhancedByS2AOP$$134e4fb$$MethodInvocation$$insert1.proceed(MethodInvocationClassGenerator.java)
  at examples.dao.DepartmentDao$$EnhancedByS2AOP$$134e4fb.insert(DepartmentDao$$EnhancedByS2AOP$$134e4fb.java)
  at examples.dao.DepartmentDaoClient.main(DepartmentDaoClient.java:19)
Caused by: com.sybase.jdbc3.jdbc.SybSQLException: The 'CREATE TABLE' command is not allowed within a multi-statement transaction in the 'tempdb' database.

  at com.sybase.jdbc3.tds.Tds.processEed(Tds.java:2942)
  at com.sybase.jdbc3.tds.Tds.nextResult(Tds.java:2246)
  at com.sybase.jdbc3.jdbc.ResultGetter.nextResult(ResultGetter.java:69)
  at com.sybase.jdbc3.jdbc.SybStatement.nextResult(SybStatement.java:220)
  at com.sybase.jdbc3.jdbc.SybStatement.nextResult(SybStatement.java:203)
  at com.sybase.jdbc3.jdbc.SybStatement.queryLoop(SybStatement.java:1698)
  at com.sybase.jdbc3.jdbc.SybCallableStatement.executeQuery(SybCallableStatement.java:103)
  at com.sybase.jdbc3.jdbc.SybDatabaseMetaData.returnResults(SybDatabaseMetaData.java:2543)
  at com.sybase.jdbc3.jdbc.SybDatabaseMetaData.getPrimaryKeys(SybDatabaseMetaData.java:2061)
  at org.seasar.framework.util.DatabaseMetaDataUtil.addPrimaryKeys(DatabaseMetaDataUtil.java:53)
  ... 13 more
Exception in thread "main" 

ポイントは、全てを単一のトランザクション下で動かさなければ、サックリと動く所かなぁ…。

環境について。

  • J2SDK 1.4.2_02
  • S2は2.2.6
  • S2DAOは、1.0.23
  • Sybaseは、Adaptive Server Enterprise 12.5.2
  • JDBCドライバは、jConnect6.0
  • 使用しているユーザは、Service Administrator(権限に関する問題は無いかなぁ…とか…)
  • テーブルは、デフォルトで作成されるmodelカタログのdboスキーマ
create table dept
       (deptno numeric(2) not null primary key,
        dname varchar(14)  null,
        loc varchar(13)  null,
        versionno numeric(8) null);

insert into dept values (10, 'accounting', 'new york', 0);
insert into dept values (20, 'research',   'dallas', 0);
insert into dept values (30, 'sales',      'chicago', 0);
insert into dept values (40, 'operations', 'boston', 0);

Sybaseは、テーブル名で大文字小文字を区別するし、nullって指定しないと、カラムにnullがはいりゃあしねぇし…

  • Department.javaだけは、ちょっとだけ修正しました。*1
public class Department implements Serializable {
  
  public static final String TABLE = "dbo.dept"; // ここより下は同じまま。s


.diconファイルの設定は以下の通り。



  
  
  
  

  
  
  
  
    
      "com.sybase.jdbc3.jdbc.SybDriver"
    
    
      "jdbc:sybase:Tds:fuelzark:5000/model"
    
    "sa"
    ""
  

  
    600
    10
    
  
  

  • DepartmentDao.dicon


  
  
  
    j2ee.requiredTx
    dao.interceptor
  

考えている対応方針について

DaoMetaDataFactoryの新しい実装を作ろうかなぁ…と思っています。
S2Containerの初期化時に.diconファイルに登録されている全てのDaoの必要なメタデータを全部集めてしまう感じ。
metaタグで、s2-daoって記述してあるか、
アスペクトとして、S2DaoInterceptorと互換性のある型のクラスを指定しているものを、処理の対象とする感じ。
これなら、別にSybase対応では無く、単なる設定上の選択肢の1つになるだけなので、良いかなぁ…と。


コードなんて書かなくても、問題無く設定の方法を知ってる方、大募集です。

人から聞いたので裏が取れていない話

  • そもそも、単一のトランザクション内で、SELECTとtempdbに対するCREATE TABLEを発行してはいけない。別な予めテーブルを作らなければいけない。
  • 但し、オプションで、非推奨だが、それを可能にする設定方法もある。


この話は、僕の個人的な感覚から言うと、ちょっと納得できていません。
何故なら、tempdbに作成されるテーブルが、ORDER BY や GROUP BYの為の一時表領域であるならば、
「tempdbに対するCREATE TABLE」って、DBで勝手に発行しているコマンドだからです。
それを、ダメって言われても…。実際、今回検証に使ったコードの中でも、CREATE TABLEなんて発行してないし。
作成される可能性のある一時表は、全て先に作っとけ。って事なんでしょうか…。何だか無茶な気がします。


この辺にある筈なんですが、どうにも読み方が甘いのか見つかりません。

*1:これがダメな理由だったり…