[[FAQ]]

*S2Dao [#y06fcbbb]
*S2Dao [#z3dec394]

#contents

**SMART deployで複数データソースに対応するには? [#w7da6e0e]

はい,可能です.~
まず,データソースごとにS2Daoのインターセプターをdiconファイルに定義する.~
そのインターセプターをAspectCustomizer#addClassPatternを使って,データソースに対応するDAOに割り当てる.~


-前提条件~
--データソースとパッケージの対応構成~
データソース1のDAOは,ルートパッケージ名.dao.dao1~
データソース2のDAOは,ルートパッケージ名.dao.dao2~

--JDBCおよびDAO関連のdiconファイルの構成~
データソース1用として,jdbc1.dicon, dao1.dicon~
データソース2用として,jdbc2.dicon, dao2.dicon~


 ---[jdbc.dicon]----------------------------------
 <components>
 	<include path="jdbc1.dicon"/>
 	<include path="jdbc2.dicon"/>
 </components>

 ---[jdbc1.dicon]----------------------------------
 <components namespace="jdbc1">
	<include path="jta.dicon"/>
	<include path="jdbc-extension.dicon"/>
 ...省略...
 	<component name="xaDataSource"
 		class="org.seasar.extension.dbcp.impl.XADataSourceImpl">
 		<property name="driverClassName">
 			"org.h2.Driver"
 		</property>
 		<property name="URL">
 			"jdbc:h2:tcp://localhost:9093/db1"
 		</property>
 		<property name="user">"sa"</property>
 		<property name="password">""</property>
 	</component>	
 ...省略...
 </components>

 ---[jdbc2.dicon]----------------------------------
 <components namespace="jdbc2">
	<include path="jta.dicon"/>
	<include path="jdbc-extension.dicon"/>
 ...省略...
 	<component name="xaDataSource"
 		class="org.seasar.extension.dbcp.impl.XADataSourceImpl">
 		<property name="driverClassName">
 			"org.h2.Driver"
 		</property>
 		<property name="URL">
 			"jdbc:h2:tcp://localhost:9093/db2"
 		</property>
 		<property name="user">"sa"</property>
 		<property name="password">""</property>
 	</component>	
 ...省略...
 </components>

 ---[dao.dicon]----------------------------------
 <components>
 	<include path="dao1.dicon"/>
 	<include path="dao2.dicon"/>
 	<include path="j2ee.dicon"/>
 </components>

 ---[dao1.dicon]----------------------------------
 <components namespace="dao1">
	<include path="jdbc1.dicon"/>
	<component name="annotationReaderFactory" class="org.seasar.dao.annotation.tiger.impl.AnnotationReaderFactoryImpl"/>
 ...省略...
 	<component name="interceptor"
 		class="org.seasar.dao.interceptors.S2DaoInterceptor"/>
 ...省略...		
 </components>

 ---[dao2.dicon]----------------------------------
 <components namespace="dao2">
	<include path="jdbc2.dicon"/>
	<component name="annotationReaderFactory" class="org.seasar.dao.annotation.tiger.impl.AnnotationReaderFactoryImpl"/>
 ...省略...
 	<component name="interceptor"
 		class="org.seasar.dao.interceptors.S2DaoInterceptor"/>
 ...省略...		
 </components>

 ---[customizer.dicon]----------------------------------
 <component name="dao1SupportAspectCustomizer" class="org.seasar.framework.container.customizer.AspectCustomizer">
 	<property name="interceptorName">"dao1.interceptor"</property>
 	<initMethod name="addClassPattern">
 		<arg>"hogehoge.dao.dao1"</arg>
 		<arg>".*Dao"</arg>
 	</initMethod>
 </component>
 <component name="dao2SupportAspectCustomizer" class="org.seasar.framework.container.customizer.AspectCustomizer">
 	<property name="interceptorName">"dao2.interceptor"</property>
 	<initMethod name="addClassPattern">
 		<arg>"hogehoge.dao.dao2"</arg>
 		<arg>".*Dao"</arg>
 	</initMethod>
 </component>
 <component name="daoCustomizer" class="org.seasar.framework.container.customizer.CustomizerChain">
 	<initMethod name="addCustomizer">
 		<arg>dao1SupportAspectCustomizer</arg>
 	</initMethod>
 	<initMethod name="addCustomizer">
 		<arg>dao2SupportAspectCustomizer</arg>
 	</initMethod>
 </component>

参考投稿:

- http://ml.seasar.org/archives/seasar-user/2007-April/009006.html
- http://ml.seasar.org/archives/seasar-user/2007-April/009012.html

Bindingアノテーションを使用する方法もあります。

- http://ml.seasar.org/archives/seasar-user/2007-September/012218.html
**どのDBに対応していますか? [#y3fc4970]

S2Daoは以下のDBに対応しています。

-Oracle
-PostgreSQL
-HSQL Database Engine
-Firebird
-Microsoft SQL Server
-MySQL
-DB2
-SAP DB (MaxDB)
-Apache Derby
-H2 Database Engine(S2Dao 1.0.38〜)

これら以外のDBでも、基本的なSELECT・INSERT・UPDATE・DELETEが使え、LEFT OUTER JOIN構文をサポートしているDBでしたら動作すると思います。

プロシージャ呼び出しについての対応状況はDBに異なるので、S2Daoのドキュメント http://s2dao.seasar.org/ja/ を確認してください。

**なんか動かないのだけれど [#f2049ffd]

- DaoにはBEANアノテーションを、JavaBeans(Entity)にはTABLEアノテーションを書きましょう。
-- BEANアノテーションの例は、Class BEAN = Employee.class;
-- TABLEアノテーションの例は、public static final String TABLE = "EMP";
- DaoにはS2DaoInterceptorを適用する必要があります。
- AbstractなDaoを使うことも可能ですが、何らかのDaoインタフェースをimplementsしている必要があります。
- バージョンアップしたら動かなくなったーー
-- dao.diconなど同梱のdiconがupdateされている可能性があります。リリースノートを確認しましょう。

**トランザクション制御はどうなっていますか? [#eef011b7]

S2Daoとしてはトランザクション制御に関与しません。
S2が持つトランザクション制御機能を利用することを想定しています。

多いパターンは、Daoを呼び出す側のコンポーネントへj2ee.requiredTxアスペクトをかけることになるでしょう。

**S2Daoを使った開発をサポートするツールはありますか? [#m94ddb63]

次のものがあります。
-[[DBFlute:http://dbflute.sandbox.seasar.org/ja/]]
-[[S2Dao-CodeGen:http://www.seasar.org/wiki/index.php?Sandbox%2FS2Dao-CodeGen]]
-[[S2Daoプラグイン:http://s2daoplugin.sandbox.seasar.org/ja/index.html]]


**updateの際に更新したくない列を指定したい [#neecea86]
>[[S2サポーター]] (2006-04-29 (土) 19:48:55)~
~
''Question''~
''Question''~
S2Daoの開発の中で、updateBatchを投げる際、更新したくない列を指定~
したいのですが、方法がわかりません。~
~
''Answer''~
''Answer''~
NO_PERSISTENT_PROPSアノテーションを使用すると更新対象に含まれなくなります。~
~
http://www.seasar.org/s2dao.html#NoPersistentPropsAnnotation~
を参照されると良いと思います。~
~
''参考投稿''~
http://ml.seasar.org/archives/seasar-user/2005-November/000360.html~
http://ml.seasar.org/archives/seasar-user/2005-November/000361.html~

//



**コネクションプーリングが行われていない? [#ufb3fde6]
>[[S2サポーター]] (2006-04-29 (土) 19:46:22)~
~
''Question''~
''Question''~
S2DAOでconnectionPoolを利用しているのですが、コネクションのプーリングが~
行なわれていないような動作をしているので、設定に漏れがあるのではないかと~
思い、何かアドバイスを頂ければとメールさせて頂きました。~
~
実行ログを見ると、最初に1件のみ~
[物理的なコネクションを取得しました]を表示して、以降はDBにアクセスする~
と[論理的なコネクションを取得しました]と出力され、1つ物理コネクションを~
使い回しているようなログが出力されています。~
~
この時に、Oracleのv$sessionを見ると論理的なコネクションの数だけセッショ~
ンが張られています。~
~
しばらくDBへのアクセスを行なわずにいるとログには[論理的なコネクション~
を取得しました]の表示がOracleに張られていたセッションの数だけ表示されま~
す。(この時、Oracelのセッションも開放されています)~
~
利用しているSeasarのバージョン~
Seasar2.2.10~
S2DAO1.0.28~
~
以下のように設定を行なっているのですが、何か過不足がありますでしょうか?~
~
 ---[j2ee.dicon]----------------------------------
 <?xml version="1.0" encoding="Shift_JIS"?>
 <!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container//EN"
 "http://www.seasar.org/dtd/components.dtd">
 <components namespace="j2ee.dicon">
 	<component name="transactionManager"
 		class="org.seasar.extension.jta.TransactionManagerImpl"/>
 	<component name="requiredTx"
 		class="org.seasar.extension.tx.RequiredInterceptor"/>
 	<component name="requiresNewTx"
 		class="org.seasar.extension.tx.RequiresNewInterceptor"/>
 	<component name="mandatoryTx"
 		class="org.seasar.extension.tx.MandatoryInterceptor"/>
 		
 	<component class="org.seasar.extension.jdbc.impl.
 BasicResultSetFactory"/>
 	<component class="org.seasar.extension.jdbc.impl.
 BasicStatementFactory"/>
 
 	
 	<component name="xaDataSource"
 		class="org.seasar.extension.dbcp.impl.XADataSourceImpl">
 		<property name="driverClassName">
 			"oracle.jdbc.driver.OracleDriver"
 		</property>
 		<property name="URL">
 			"jdbc:oracle:thin:@192.168.0.5:1521:white"
 		</property>
 		<property name="user">"serverwatcher"</property>
 		<property name="password">"serverwatcher"</property>
 	</component>
 	
 	<component name="connectionPool"
 		class="org.seasar.extension.dbcp.impl.ConnectionPoolImpl
 ">
 		<property name="timeout">600</property>
 		<property name="maxPoolSize">10</property>
 		<destroyMethod name="close"/>
 	</component>
 	<component name="dataSource"
 		class="org.seasar.extension.dbcp.impl.DataSourceImpl"/>
 	
 
 </components>
 ----------------------------------------------------
>~
 ---[dao.dicon]--------------------------------------
 <?xml version="1.0" encoding="Shift_JIS"?>
 <!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container//EN"
 "http://www.seasar.org/dtd/components.dtd">
 <components namespace="dao">
 	<include path="j2ee.dicon"/>
 	<component
 		class="org.seasar.dao.impl.DaoMetaDataFactoryImpl"/>
 	<component name="interceptor"
 		class="org.seasar.dao.interceptors.S2DaoInterceptor">
 			<aspect>dao.requiredTx</aspect>
 	</component>
 </components>
 ----------------------------------------------------
>~
''Answer''~
''Answer''~
原因は ServerControllerの constructorにありますね。~
S2Containerを要求ごとに diconファイルから構築しているので、結局のとこ~
ろVM空間上に複数のコンポーネントセットが存在することになります。~
~
ということは、DataSourceもConnectionPoolも複数あるので、ログにあるよう~
な動きになります。~
~
S2の挙動というよりかは、DIの適用パターンにあわせて設計・動きを少し変更~
されたほうがよろしいかと思います。~
~
私なら以下の方法を使います~
~
   1. EditLogic が xxxDao を使う(必須)のであれば EditLogicのコンストラ
      クタに引数を追加し、default constructorを削除する。
      これは
         public EditLogic(xxxDao dao) {
            this.dao = dao;
         }
      のようにする
   2. EditLogicは diconに定義する(か、自動登録されるような規則に従った
      上でAutoRegisterを使う)
      これでEditLogicのインスタンス管理はコンテナのもとにあります
   3. EditLogicが必要な部分は S2を経由してインスタンスを取得するように
      します。たとえば、EditLogicが StrutsのActionなのであれば S2Struts
      を用います.
      new EditLogic() している場所を getComponent(EditLogic.class) のよ
      うにすればいいかと思いますが、この方法を用いるのであればインタフェー
      スと実装クラスに分離したほうが良いです。
     (S2JSFの場合は特に意識する必要すらないと思います)
~
~
''参考投稿''~
http://ml.seasar.org/archives/seasar-user/2005-November/000446.html~
http://ml.seasar.org/archives/seasar-user/2005-November/000481.html~

//



**S2DAO、S2JDBC等のSQL発行方法について [#ef02361c]
>[[S2サポーター]] (2006-04-29 (土) 19:42:46)~
~
''Question''~
''Question''~
~
S2DAO、S2JDBC等でSQLを発行する際にコンパイル済みのSQLを発行するのか、~
毎SQLを生成して発行するのか、どちらなのでしょう?サンプルのログをみてい~
ると毎回生成しているように思えるのですが。。。~
~
''Answer''~
''Answer''~
~
PreparedStatementに格納してあるプリコンパイルされたSQLを発行しています。~
~
ログではき出されているSQLは、Statementに渡される(発行する)SQLを~
そのまま表示している訳ではなく、ログにはき出すためにS2が、パラメータが~
埋め込まれたSQLをせっせと作っています。~
~
org.seasar.extension.jdbc.impl.BasicHandlerクラスの~
getCompleteSqlメソッドが参考になると思います。~
http://www.seasar.org/websvn/filedetails.php?repname=s2container&path=%2Ftrunk%2Fseasar2%2Fs2-extension%2Fsrc%2Fmain%2Fjava%2Forg%2Fseasar%2Fextension%2Fjdbc%2Fimpl%2FBasicHandler.java&rev=0&sc=0~
http://svn.seasar.org/browse/trunk/seasar2/s2-extension/src/main/java/org/seasar/extension/jdbc/impl/BasicHandler.java?root=s2container&view=markup~

~
''参考投稿''~
http://ml.seasar.org/archives/seasar-user/2005-November/000431.html~
http://ml.seasar.org/archives/seasar-user/2005-November/000452.html~

//



**S2DaoでJDKを変えるとClassCastException [#n8b74b01]
>[[S2サポーター]] (2006-04-29 (土) 19:40:26)~
~
''Question''~
''Question''~
~
S2DaoでJDK1.4.2_08だと動くコードがJDK1.4.2_10にして~
Daoのメソッドを呼ぶとClassCastExceptionでこけてしまうコードがあります。~
~
DaoのメソッドはBigDecimalを返すメソッドで引数4つを取ります。~
 public BigDecimal sumTest(String a, String b, String c, String d,
  String e);
 public static final String sumTest_ARGS = "a,b,c,d";
~
SQLファイルは~
 select 
 sum(qty)
 from testdat s 
 left outer join xx l on s.hoge = l.hoge and s.hoge2 = l.hoge2
 where s.a = /*a*/'a'
 and s.b = /*b*/'b'
 and s.c = /*c*/'0'
 and l.d = /*d*/'1'
~
となっています(フィールド名等はサンプルです)~
スタックトレースは~
 java.lang.ClassCastException
 	at sun.nio.cs.ext.JISAutoDetect$Decoder.decodeLoop(Unknown Source)
 	at sun.nio.cs.ext.JISAutoDetect$Decoder.decodeLoop(Unknown Source)
 	at java.nio.charset.CharsetDecoder.decode(Unknown Source)
 	at sun.nio.cs.StreamDecoder$CharsetSD.implRead(Unknown Source)
 	at sun.nio.cs.StreamDecoder.read(Unknown Source)
 	at java.io.InputStreamReader.read(Unknown Source)
 	at java.io.BufferedReader.read1(Unknown Source)
 	at java.io.BufferedReader.read(Unknown Source)
 	at java.io.Reader.read(Unknown Source)
 	at org.seasar.framework.util.ReaderUtil.readText(ReaderUtil.java:27)
 	at org.seasar.framework.util.TextUtil.readText(TextUtil.java:18)
 	at org.seasar.dao.impl.DaoMetaDataImpl.setupMethod(DaoMetaDataImpl.java:132)
 	at org.seasar.dao.impl.DaoMetaDataImpl.setupSqlCommand(DaoMetaDataImpl.java:112)
 	at org.seasar.dao.impl.DaoMetaDataImpl.<init>(DaoMetaDataImpl.java:103)
 	at org.seasar.dao.impl.DaoMetaDataFactoryImpl.getDaoMetaData(DaoMetaDataFactoryImpl.java:42)
 	at org.seasar.dao.interceptors.S2DaoInterceptor.invoke(S2DaoInterceptor.java:34)
 	at org.seasar.framework.aop.impl.NestedMethodInvocation.proceed(NestedMethodInvocation.java:26)
 	at org.seasar.framework.aop.interceptors.TraceInterceptor.invoke(TraceInterceptor.java:33)
 	at org.seasar.framework.aop.impl.NestedMethodInvocation.proceed(NestedMethodInvocation.java:26)
 	at org.seasar.framework.aop.interceptors.InterceptorChain.invoke(InterceptorChain.java:24)
 	at test.TestDatDao$$EnhancedByS2AOP$$18622f3$$MethodInvocation$$sumTest5.proceed(MethodInvocationClassGenerator.java)
 	at test.TestDatDao$$EnhancedByS2AOP$$18622f3.sumTest(TestDatDao$$EnhancedByS2AOP$$18622f3.java)
~
となっております。~
SQLを組み立てる時にこけている様な感じです。~
DAOのバージョンはs2-dao-1.0.28.jarでPostgreSQL8.0.3を使っております。~
JDKの違いやdaoのバージョンで何か注意する点等ありますでしょうか?~
~
''Answer''~
''Answer''~
~
JDK 1.4.2_10にはJISAutoDetectのバグがあります。~
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=25802&forum=12~
~
FIXされるまで1.4.2_10より前のバージョンを使われることをオススメします。~
~
''参考投稿''~
http://ml.seasar.org/archives/seasar-user/2005-November/000429.html~
http://ml.seasar.org/archives/seasar-user/2005-November/000430.html~

//



**プライマリキーが無いテーブルにS2DAOでアクセスしたい [#v3762873]
>[[S2サポーター]] (2006-04-29 (土) 19:33:05)~
~
''Question''~
~
S2Daoのプライマリーキーの処理について伺います。~
~
S2Daoを使ってDB2へのアクセスを勉強しております。~
テーブルにプライマリーキーが設定していないと、S2Daoが~
「・・にプライマリーキーが見付りません」の例外を投げてきます。~
当然テーブルに直接プライマリーキーが設定していれば問題が~
ありませんが、既存のテーブルに明示的に主キーではなく、~
Index(索引)の形で主キーを指定されていることです。~
~
この場合はS2Daoをどのようにすれば~
「・・にプライマリーキーが見付りません」の例外を回避できるのでしょうか。~
~
''Answer''~
UPDATEやDELETEなどの自動生成を行わなければ、プライマリキー~
がなくても問題ありません。~
したがって、UPDATEやDELETEをsqlファイルやsqlコメントで行えば~
例外を回避できると思います。~
~
''参考投稿''~
http://ml.seasar.org/archives/seasar-user/2005-October/000626.html~
http://ml.seasar.org/archives/seasar-user/2005-October/000632.html~
>[[S2サポーター]] (2006-04-29 (土) 19:33:05)

''Question''

S2Daoのプライマリーキーの処理について伺います。
S2Daoを使ってDB2へのアクセスを勉強しております。

テーブルにプライマリーキーが設定していないと、S2Daoが「・・にプライマリーキーが見付りません」の例外を投げてきます。

当然テーブルに直接プライマリーキーが設定していれば問題がありませんが、既存のテーブルに明示的に主キーではなく、Index(索引)の形で主キーを指定されていることです。

この場合はS2Daoをどのようにすれば「・・にプライマリーキーが見付りません」の例外を回避できるのでしょうか。

''Answer''

UPDATEやDELETEなどの自動生成を行わなければ、プライマリキーがなくても問題ありません。これは、UPDATEやDELETE文のWHERE句にPKを含むよう自動生成するためです。
したがって、UPDATEやDELETEをsqlファイルやsqlコメントで行えば例外を回避できると思います。

DAOがUPDATEやDELETEメソッドを持たない場合は、何か対応する必要はありません。

テーブルにはPKを付けることを推奨します。

''参考投稿''

-Q: http://ml.seasar.org/archives/seasar-user/2005-October/000626.html~
-A: http://ml.seasar.org/archives/seasar-user/2005-October/000632.html~

//



**S2で複数DBとのコネクションを取得する方法は? [#q70fa8ce]
>[[S2サポーター]] (2006-04-29 (土) 19:30:14)~
~
''Question''~
''Question''~
j2ee.diconでの設定を利用すれば自動的に1個のコネクションを得られます。~
複数DBとのコネクションを取得するにはどうすればよいのでしょうか。~
~
''Answer''~
''Answer''~
~
まず,j2ee.dicon をコピーして DB 接続ごとの dicon ファイルを~
作成してください.~
例えば ds1.dicon~
~
 <components namespace="ds1">
     <include path="j2ee.dicon"/>
 
     <component name="dataSource" class="...">
         ・・・
     </component>
     <component name="xaDataSource" class="...">
         ・・・
     </component>
     <component name="connectionPool" class="...">
         ・・・
     </component>
 </component>
~
必要なコンポーネントは 3 つだけです.~
transactionManager 等のコンポーネントは削除してください.~
~
同じように ds2.dicon も作成します.~
~
そして j2ee.dicon から name 属性が以下の値になっている<component> 要素を削除します.~
~
dataSource~
xaDataSource~
connectionPool~
~
ds1.dicon で記述したコネクションを使用するコンポーネント用の~
dicon は ds1.dicon をインクルードします.~
例えば app1.dicon~
 <components namespace="app1">
     <include path="ds1.dicon"/>
     ・・・
 <components>
~
ds2.dicon で記述したコネクションを使用するコンポーネント用の~
dicon は ds2.dicon をインクルードします.~
例えば app2.dicon~
~
 <components namespace="app2">
     <include path="ds2.dicon"/>
     ・・・
 <components>
~
もし,ds1.dicon と ds2.dicon に記述したコネクションを同時に~
使用するコンポーネントがある場合は,両方をインクルードして~
コンポーネントのプロパティに明示的に DataSource を設定します.~
例えば app3.dicon~
~
 <components namespace="app3">
     <include path="ds1.dicon"/>
     <include path="ds2.dicon"/>
 
     <component name="..." class="...">
         <property name="dataSource1">ds1.dataSource</property>
         <property name="dataSource2">ds2.dataSource</property>
         ・・・
     </component>
     ・・・
 </components>
~
~
最後に,app1.dicon や app2.dicon,app3.dicon 等を app.dicon に~
インクルードします.~
~
 <components>
     <include path="app1.dicon"/>
     <include path="app2.dicon"/>
     <include path="app3.dicon"/>
     ・・・
 </components>
~
~
実際に確認していないので間違いがあるかもしれませんが,~
だいたいこんな感じでできるかと思います.~
~
''参考投稿''~
http://ml.seasar.org/archives/seasar-user/2005-October/000574.html~
http://ml.seasar.org/archives/seasar-user/2005-October/000575.html~
''参考投稿''
- http://ml.seasar.org/archives/seasar-user/2005-October/000574.html
- http://ml.seasar.org/archives/seasar-user/2005-October/000575.html
- http://ml.seasar.org/archives/seasar-user/2006-July/005979.html

//
追記: SelectableDataSourceProxyを使う方法もあります。
http://ml.seasar.org/archives/seasar-user/2006-May/005597.html はちょっと情報が古いですね。。。



**複雑なSQLを処理する場合の実装方法 [#j36201a2]
>[[S2サポーター]] (2006-04-29 (土) 19:26:23)~
~
''Question''~
''Question''~
複雑なSQLを処理する場合の実装方法について教え頂けませんでしょうか?~
~
''Answer''~
''Answer''~
引数の値をSQL文に文字列として直接埋め込む。[[ドキュメント:http://s2dao.seasar.org/ja/s2dao.html]]の~
「埋め込み変数コメント」を参照。~
~
''参考投稿''~
http://ml.seasar.org/archives/seasar-user/2005-December/000288.html~
http://ml.seasar.org/archives/seasar-user/2005-December/000301.html~

//



**S2DAOで幾何データ演算子を使いたい [#u7f14c3b]
**幾何データ演算子を使いたい [#u7f14c3b]

>[[S2サポーター]] (2006-04-29 (土) 18:45:30)~
~
''Question''~
''Question''~
s2daoを使用して、PostgresSQLの幾何データ型を扱っているのですが、~
PostgresSQLがサポートしている幾何データ演算子の中には~
?# のように「?」を含む演算子があります。~
~
例:select A.name from road as A, road as B where A.path ?# B.path and~
B.name = 'hoge';~
~
この演算子を使用したSQLを発行しようとすると、「?」がバインド変数とみなされ~
て、~
java.sql.SQLExceptionが発生してしまいます。~
~
ログで実行されたSQLをみてみると、~
select A.name from road as A, road as B where A.path null# B.path and B.name~
= 'hoge';~
となっています。~
~
org.seasar.framework.util.PreparedStatementUtilで~
java.sql.PreparedStatementを使用している以上、~
s2daoでPostgresSQLの幾何データ演算子を使用することはできないのでしょうか?~
~
ちなみに、単独でjava.sql.Statementを使用して同じSQLを発行すると、~
正常に問い合わせが行われました。~
~
何かよい方法があれば、教えてください。~
よろしくお願い致します。~
~
~
''Answer''~
''Answer''~
CREATE OPERATOR文を使用して、新しく作成したOPERATORの中でpath_interを~
呼び出すことで、無事解決することができました。~
~
''参考投稿''~
http://ml.seasar.org/archives/seasar-user/2006-January/000175.html~
http://ml.seasar.org/archives/seasar-user/2006-January/000176.html~
http://ml.seasar.org/archives/seasar-user/2006-January/000177.html~
http://ml.seasar.org/archives/seasar-user/2006-Janu

//
**配列からINへのバインドで例外が出る [#s0fbdde7]

- Q: http://ml.seasar.org/archives/seasar-user/2006-July/006091.html
- A: http://ml.seasar.org/archives/seasar-user/2006-July/006102.html

ドキュメントに

**接続先DBを動的に変更したい [#z13fc424]
>[[S2サポーター]] (2006-04-29 (土) 18:39:45)~
~
''Question''~
~
j2ee.diconで定義しているxaDataSourceのdriverClassNameや、URLなどの値~
を、他外部ファイルの値にプログラム内で置き換え、変更後はその変更した~
値でDBにアクセスすることは可能でしょうか?~
~
 例)
  ・j2ee.diconファイルの情報
    driverClassName =oracle.jdbc.driver.OracleDriver
    URL = jdbc:oracle:thin:@xxx:1521:yyy
      :
     
       ↓ 動的に、外部ファイルの内容に置き換えたい。
     
  ・外部ファイルの情報
       driverClassName =org.postgres.jdbc.driver.PostgresDriver
      URL=jdbc:postgresql://localhost:5432:yyy
~
 j2ee.dicon 一部抜粋 ---------
 
 <component name="xaDataSource" class="org.seasar.extension.dbcp.impl.
 XADataSourceImpl">        
 	<property name="driverClassName">
           "oracle.jdbc.driver.OracleDriver"        
        </property>
        <property name="URL">            
           "jdbc:oracle:thin:@xxx:1521:yyy"        
        </property>
        <property name="user">
          "aaa"
        </property>  
        <property name="password">
          "bbb"
        </property>
 IN /*引数名*/(...)

とあるように、

 IN /*dto.aaa*/('aaa')

というふうにコメントより後ろの括弧が必要。

**バッチ更新の途中でエラーになった場合に、何件目でエラーになったか知りたい [#r06c4127]

- Q: http://ml.seasar.org/archives/seasar-user/2006-August/006204.html
- A: http://ml.seasar.org/archives/seasar-user/2006-August/006213.html

JDBC APIから知る方法が無いため、無理。
< java.sql.Statement#executeBatch()を使用しているのであれば、戻り値のint[]に各コマンドの実行結果が反映されているはずですよね?現実的には、1つのコマンドでも失敗すれば、全てのコマンドが失敗したような状態になってしまった記憶があります。つまりJDBCドライバー次第ってことですね。

**SQL文の変数部分にクラス名が含まれてしまう [#xc2b524b]

-Q: http://ml.seasar.org/archives/seasar-user/2006-August/006203.html
-A: http://ml.seasar.org/archives/seasar-user/2006-August/006205.html

''Question''

SQLのパラメータ?の部分に、以下のような文字列が入ってしまいます。

 WHERE
   USER./*searchKey*/USER_ID LIKE /*searchValue*/'%t%'
    ↓↓↓↓↓↓↓
 WHERE
   USER.'s2.dao.user.UserPagerCondition@1b35125' LIKE 's2.dao.user.UserPagerCondition@1b35125'

''Answer''

Dao側が

 public List findUserByDto(UserPagerCondition dto);

である場合には、SQL側を

 USER./*dto.searchKey*/USER_ID LIKE /*dto.searchValue*/'%t%'

のように"dto"を付けてみて頂けますか?

**排他制御のTimestamp値にDB側の時間をセットしたい [#rba69c39]

-Q: http://ml.seasar.org/archives/seasar-user/2006-July/006062.html
-A: http://ml.seasar.org/archives/seasar-user/2006-August/006139.html

排他制御には、TimestampよりもVersionNoの方が良い。
レコード更新時の時間を持ちたいのならば、トリガーを使うのが良いのでは。

**BLOB型を扱えますか? [#t6a127bb]

はい、扱えます。
JavaBeansのプロパティをbyte[]型にしておくと、S2DaoはPreparedStatementに対してsetBinaryStream、ResultSetに対してgetBytesを呼び出すようになります。

**OracleでBLOB型を扱えないようだけれど? [#rfd9e52c]

-Q: http://ml.seasar.org/archives/seasar-user/2006-October/006749.html
-A: http://ml.seasar.org/archives/seasar-user/2006-October/006751.html

OracleのThinドライバではPreparedStatement#setBinaryStream()がサポートされていないようで、

- java.sql.Blobを使う
- ThinドライバではなくOCIドライバを使う

と言った解決方法があるようです。

※バージョンにもよると思いますので、追加情報をお持ちの方にコメント頂きたいです。

**3つ以上のテーブルをJOINしたい [#nb9c011d]

-Q: http://ml.seasar.org/archives/seasar-user/2006-October/006707.html
-A: http://ml.seasar.org/archives/seasar-user/2006-October/006745.html

**Sybaseでストアドプロシージャ実行時にFetchSizeが指定されているとエラーになる [#y8277c1f]

[Seasar-user:5457] のスレッドを参照。

- http://ml.seasar.org/archives/seasar-user/2006-December/007372.html

**MySQLでクエリキャッシュがヒットしない [#wdcd2de2]

[Seasar-user:5447] のスレッドを参照。

-Q: http://ml.seasar.org/archives/seasar-user/2006-December/007362.html
-A: http://ml.seasar.org/archives/seasar-user/2006-December/007387.html

**DB2でBLOB型のデータを取得時に例外が発生する [#m07b22ad]

[Seasar-user:5458]のスレッドを参照。

-Q: http://ml.seasar.org/archives/seasar-user/2006-December/007373.html
-A: http://ml.seasar.org/archives/seasar-user/2006-December/007396.html

**更新結果が0件の時に例外を発生させたくない [#ce7c8396]

SQLファイルないしSQLアノテーションでSQLを記述してください。

- http://d.hatena.ne.jp/duran/20070119#p1

**PosgreSQLとS2Pagerの組み合わせで、limitとoffsetを使用した高速取得使用時にSQLExceptionが発生する。 [#d718f3a3]

j2ee.dicon又はjdbc.diconの接続文字列にオプション「protocolVersion=2」を付いているか確認してください。

- http://s2dao.seasar.org/ja/s2pager.html#LimitOffset

**ヒット数が0件の場合はnullが返るの? [#t2696db0]

戻り値を配列かListで宣言しているSelect系メソッドの場合は、要素数0の配列かListがreturnされます。
nullではありません。

**バッチ更新の場合、IDアノテーションが無視される [#r16e487f]
現行のS2Daoの仕様です。

これはバッチ更新の場合、複数レコードの更新・削除をまとめて行うためID値の取得を行うタイミングがないためです。(1件ずつINSERTする場合はINSERT文を発行する直前にSEQUENCEからnextvalを取得していますが、バッチ更新の場合はnextvalを取得するタイミングが無いため。)

**OracleのNUBER型のカラムにBEAN側のInteger型プロパティを組み合わせると、Insert/Update時に値がとんでもなくなる(例8.3000000000000000000000000000000000E+83)場合がある。 [#bcef7a42]
OracleとJDBCドライバの組み合わせによって、この現象が起きることが報告されています。

参考:

http://ml.seasar.org/archives/seasar-user/2006-September/006567.html

http://ml.seasar.org/archives/seasar-user/2007-March/008602.html

**以下のような例外が出力されます [#pca39e4d]
>org.seasar.dao.MethodSetupFailureRuntimeException: [EDAO0019]test.dao.TestDaoの
> updateメソッドの初期化時に例外が発生しました。理由はorg.seasar.dao.PrimaryKeyNotFoundRuntimeException: 
>[EDAO0009]test.dto.TestDto$$EnhancedByS2AOP$$423a423aにプライマリーキーが見つかりません

原因は三つ考えられます。
-TestDtoのTABLEアノテーションで指定したテーブルに、プライマリーキーがないか、ユニークキーのみ設定されている。
-TABLEアノテーションで指定した''テーブル名が間違っている''。
-Beanのプロパティ名(メソッド名/変数名)が間違っている(カラム名に対応していない)

**IDアノテーションのidentity/sequenceはどのDBが対応していますか? [#n8024f9b]
リンク先の表をごらんください。
http://s2dao.seasar.org/ja/s2dao.html#IDAutoGenerate

**IDアノテーションが機能しない [#ocd1ed37]
IDアノテーションを使用してIDの自動設定を行う場合、Daoが使うDataSourceにトランザクションがかかっている必要があります。

**isolationレベルを変更したい [#t3335ca5]

データソース毎にisolationレベルを変更可能です。

diconファイルにて、ConnectionPoolImplのtransactionIsolationLevelプロパティにConnection.TRANSACTION_SERIALIZABLEなどを指定してください。

アプリケーション内で複数のtransactionIsolationLevelを使い分けたい場合は、複数のConnectionPoolImplをdiconで設定してください。

**Daoのメソッド呼び出し時にorg.seasar.dao.MethodSetupFailureRuntimeExceptionが発生しました。 [#j82206a8]
この例外は、Daoのメソッドが最初に呼ばれたときに、''呼び出したメソッドでなく、Daoの全メソッドの中のいずれか''を初期化するときに例外になったことをさしています。

例外メッセージ中に、例外の原因となったメソッドの名前が表示されているので、そのメソッドの定義を見直してください。
**プライマリーキーのみのテーブルで例外 [#kf22bc03]
プライマリーキーのみのテーブルに対するDaoを作成したところ、以下のような例外が出ました。

 org.seasar.dao.MethodSetupFailureRuntimeException:
 [EDAO0019]jp.roaso.dao.UsrgrpassignedDaoのupdateメソッドの初期化時に例外が発生しました。
 理由はorg.seasar.framework.exception.SRuntimeException: 
 [EDAO0020]Primary KeyのみのテーブルをSQL文の自動生成で更新することはできません

更新SQLを自動生成しているメソッドを削除してください。

例えば
 public class Employee{
    private int empno;
    private int companyno;
 (setter/getter略)
 }

のようなEntityがあった場合、empnoがPKだとS2Daoは
 update Employee set companyno = ? where empno = ?
のようなSQL文を生成するわけですが、
empnoとcompanynoが両方PKだとSQL文が
 update Employee set where emono = ? and companyno = ?
となり、SQL文として意味を成しません。

このため、Daoの初期化時(Dao中のいずれかのメソッドが最初に呼ばれたとき)に、PKだけのテーブルに対してSQL文の自動生成を行うメソッドがあった場合には例外にするようになっています。

**BooleanToIntStatementFactoryとPagerStatementFactoryを併用したい [#r6bab544]
j2ee.diconまたはjdbc.diconのPagerStaementFacotoryにbooleanToIntプロパティを追加してください。
 <component class="org.seasar.dao.pager.PagerStatementFactory">
     <property name="booleanToInt">true</property>
 </component>
 
 -----------------------------
~
なぜ上記のような質問をしたかと言いますと、現在「S2DAOを使用しDBにア~
クセスするサーバ常駐プログラム」を開発しており、設定ファイルなどを使用~
して動的に接続先DBを変更できる仕様を検討しているためです。~
~
以下URLに記載されているように、DAOクラスにてprivate変数にDataSource~
を定義して、コネクション取得時にURLなどの情報を変更することもできそ~
うですが、なるべくDAO実装クラスを書きたくありません。~
(DAOインタフェースのみで対処したい)~
~
http://www.seasar.org/dbcp.html~
~
~
''Answer''~
【Answer1】~
私もアプリ起動中の動的な接続先データベースの変更~
(スキーマもDBMSも完全にコンパチで拠点だけ2つある(テスト系:本番系のよう~
な)イメージ)を以下の方法で実施しています~
~
1. connectionPoolを複数設定 (接続先ごとに)~
2. DataSourceを継承したクラスを作成~
2-1. connectionPoolを動的に変更できるsetterを準備しておく~
3. 必要なときに setterを読んで接続先を変更する~
4. あとは S2Daoでもなんでも...~
~
ただし、この方法でS2Daoの接続先を変更する場合には、複数の接続先はDBMS~
も含めてほぼ?コンパチである必要があると思います。~
(DBMSの情報を取得していますから > S2DaoInterceptor)~
~
ですので、ご質問の内容で driverClassまで置き換えることが前提となってい~
るようですのでこの方法ではS2Daoは誤動作する可能性があると思います。~
(DaoMetaDataImplのコンストラクタ内でDBMS情報を取得しているようです)~
~
Daoインタフェースから参照しているエンティティも同様ですので、テーブル~
構造が微妙に違う場合も同様の問題がありますね.~
~
当方はWebアプリということもあり以下のようなことになっています~
~
a. sessionスコープの "コネクション先情報" コンポーネントを用意~
b. 継承したDataSourceから sessionスコープの上記コンポーネントをget~
 (するとユーザーごとの接続先データベースが取得できる)~
c. connectionPoolのsetterは この"コネクション先情報"コンポーネントに格納する (=sessionに格納される)~
~
このコンポーネントは ConnectionPoolのフィールドを1つだけ持つJavaBeanで~
充分です。~
~
やり方としてはエレガントではないかもしれませんがいまのところ機能してい~
ます。~
~
~
【Answer2】~
 <component name="props">
   <initMethod>@org.seasar.framework.util.ResourceUtil @ getProperties('abc.properties')</initMethod>
 </component>
 <component name="xaDataSource" class="org.seasar.extension.dbcp.impl.
 XADataSourceImpl">        
   <property name="URL">props.URL</property>
   ...
 </component>
~
みたいなかんじでできますよ。~
abc.propertiesは、この例だとCLASSPATHに通されているディレクトリの~
ルートに置いてください。~
~
動的にっていっているところが意図するところと合ってないかもしれませんが。~
~
~
''参考投稿''~
http://ml.seasar.org/archives/seasar-user/2006-March/005258.html~
http://ml.seasar.org/archives/seasar-user/2006-March/005259.html~
http://ml.seasar.org/archives/seasar-user/2006-March/005262.html~

//
**SQLをツールで実行すると結果が取得できるのに、そのSQLをS2Dao経由で実行すると結果が取得できない。 [#z51d0640]
WHERE句でCHAR型のカラムを利用し、そのカラム定義と異なる長さの値をバインドしているとこの現象が起こる場合があります。
-参考
--https://www.seasar.org/issues/browse/DAO-4

**CREATE/DROP/TRUNCATEなどのSQLを実行したい [#bf14283e]
exexuteQuery/executeUpdateで実行できるSQLなら、実行することができます。

その場合、メソッドの名前をexexuteQueryなら検索、executeUpdateなら挿入/更新/削除の[[命名規則:http://s2dao.seasar.org/ja/s2dao.html#MethodNaming]]にあわせてください。

**条件を設定してCountを実行する方法は? [#nce57178]
>[[S2サポーター]] (2006-04-29 (土) 18:37:25)~
~
''Question''~
S2DAOでcount(*)のSQLに条件を入れて実行すると必ず件数が0件と返ってきます。~
条件なしに実行すると件数は取得できます。~
~
書き方が誤っているのでしょうか。~
条件があっても件数を取得できる方法を教えていただけますでしょうか。~
~
よろしくお願いします。~
~
 --------------------- 簡易ソース ----------------------
 DAOクラス
 public static final Class BEAN = HogeDto.class;
 public static final String getCount_ARGS = "hoge";
 int getCount(String hoge);
 
 DTOクラス
 省略
 
 SQLファイル
 SELECT COUNT(*) FROM AAAA WHERE HOGE = /*hoge*/
 -------------------------------------------------------
~
''Answer''~
SQL自体は正しかったのですが、SQLコメントにyear,monthなど予約語で使われている~
ものを使用すると条件が無視されていることがわかりました。~
~
なのでyear,monthのSQLコメントをintYear,intMonthに直して実行すると件数の取得ができました。~
~
~
''参考投稿''~
http://ml.seasar.org/archives/seasar-user/2006-March/005349.html~
http://ml.seasar.org/archives/seasar-user/2006-March/005351.html~
http://ml.seasar.org/archives/seasar-user/2006-March/005355.html~
ただし、オラクルは、[[DML:http://e-words.jp/w/DML.html]]以外をPreparedStatementで実行すると不安定になるので、S2Daoから実行するのは、やめたほうが良いと思います。

//
truncateなどは、Statementで実行してください。

#DataSourceから自前で処理するという意味です。

**IFコメントを使用した場合にQueryアノテーションで指定したクエリ全体が無視されてしまう [#gd054636]
すべてのIFコメントがfalseと評価され、かつELSEコメントがない場合に起こります。
対策としては次のような方法があります。
-BEGINコメントと併用する
-ELSEコメントと併用する
-条件の指定順を変更する http://ml.seasar.org/archives/seasar-user/2007-April/009109.html

**データベースアクセス時にタイムアウトさせたい [#i360044e]
>[[S2サポーター]] (2006-04-29 (土) 18:36:01)~
~
''Question''~
S2daoを使ってDBにアクセスする際に、~
statementのqueryTimeoutを設定することはできないのでしょうか?~
~
SQLを投げて処理が重くてかえってこない場合にタイムアウト~
にしたいのですが。。。~
~
DBはオラクルを使っています。~
~
''Answer''~
もし、Dao全体で、1つのqueryTimeoutでいいのでしたら、~
org.seasar.extension.jdbc.StatementFactoryを自分で継承した~
クラスを作り、j2ee.diconの~
 <component class="org.seasar.extension.jdbc.impl.BasicStatementFactory"/>
のところを置き換えればできると思います。~
~
Daoごとに、queryTimeoutの値を変えたいのでしたら、~
http://groovetube.org/index.php?itemid=183&catid=6~
こちらのページを参考にして、queryTimeoutごとにdao.diconを~
作ればできなくはないと思います。~
~
あるメソッドだけ、queryTimeoutの値を変えたい場合は申し訳ないのですが、~
今はできないと思います。~
~
~
''参考投稿''~
http://ml.seasar.org
**S2Pagerのオフセットのはじまりは「1」「0」どちらですか? [#ud82e9e3]
S2Pagerのオフセットは「0」からはじまります。OracleRownumPagingSqlRewriterを使用する場合、SQLではオフセットでなく開始位置を指定するので、
 SELECT
        *
    FROM
        (
            SELECT
                    ROWNUM AS S2DAO_ROWNUMBER
                    ,S2DAO_ORIGINAL_DATA.*
                FROM
                    (
                        SELECT
                                EMPNO,
                                ENAME,
                                SAL,
                                COMM,
                                DEPTNO
                            FROM
                                EMP
                    ) S2DAO_ORIGINAL_DATA
        )
    WHERE
        S2DAO_ROWNUMBER BETWEEN 1 AND 50
        AND ROWNUM <= 50
    ORDER BY
        S2DAO_ROWNUMBER
のように、オフセットで「0」を指定すると「1」ではじまるSQLが実行されますが、これは仕様となります。

**ツールで実行した場合は問題ないSQLがS2Pager(OracleRownumPagingSqlRewriter)使用時にSQLException(ORA-00918: column ambiguously defined )になる [#s8b646b9]
S2PagerのOracleRownumPagingSqlRewriterはオリジナルのSQLをサブクエリとして実行します。このため、例えば
  SELECT
          *
      FROM
          DUAL A
          ,DUAL B
      WHERE
          A.DUMMY = B.DUMMY
のように、同じカラム(エイリアス)をSELECTするSQLをOracleRownumPagingSqlRewriterを使用して実行すると、外側のクエリで列を特定できないためSQLExceptionになる場合があります。
  SELECT
          *
      FROM
          DUAL A join DUAL B
      ON
          A.DUMMY = B.DUMMY
のように標準SQLの結合構文の場合はエラーが出ませんが、今度はメタデータからカラム名を取得できないのでS2Dao側で値をセットできなくなりますので、クエリ内ではカラム名を必ず指定することをおすすめします。

**SQLインジェクションへ気をつける必要がありますか? [#d9e86175]

自動生成SQLや、*.sqlファイルへのバインドを使用する場合は、インジェクション対策は不要です。

インジェクション対策が必要なのは、

- 埋め込み変数コメントを使う場合
- EntityManagerでSQL文を文字列結合して作成する場合

です。"'" + 入力値 + "'"のようにSQLを組み立てる際に入力値をエスケープしてください。


トップ   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS