FAQ/S2DAO
の編集
https://www.seasar.org/wiki/?FAQ/S2DAO
[
トップ
] [
編集
|
差分
|
履歴
|
添付
|
リロード
] [
新規
|
一覧
|
検索
|
最終更新
|
ヘルプ
|
ログイン
]
-- 雛形とするページ --
CreateSandboxJavaProjectTemplateWithMaven2
[[FAQ]] *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''~ S2Daoの開発の中で、updateBatchを投げる際、更新したくない列を指定~ したいのですが、方法がわかりません。~ ~ ''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''~ 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''~ 原因は 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''~ ~ S2DAO、S2JDBC等でSQLを発行する際にコンパイル済みのSQLを発行するのか、~ 毎SQLを生成して発行するのか、どちらなのでしょう?サンプルのログをみてい~ ると毎回生成しているように思えるのですが。。。~ ~ ''Answer''~ ~ PreparedStatementに格納してあるプリコンパイルされたSQLを発行しています。~ ~ ログではき出されているSQLは、Statementに渡される(発行する)SQLを~ そのまま表示している訳ではなく、ログにはき出すためにS2が、パラメータが~ 埋め込まれたSQLをせっせと作っています。~ ~ org.seasar.extension.jdbc.impl.BasicHandlerクラスの~ getCompleteSqlメソッドが参考になると思います。~ 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''~ ~ 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''~ ~ 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文の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''~ j2ee.diconでの設定を利用すれば自動的に1個のコネクションを得られます。~ 複数DBとのコネクションを取得するにはどうすればよいのでしょうか。~ ~ ''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/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''~ 複雑なSQLを処理する場合の実装方法について教え頂けませんでしょうか?~ ~ ''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~ // **幾何データ演算子を使いたい [#u7f14c3b] >[[S2サポーター]] (2006-04-29 (土) 18:45:30)~ ~ ''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''~ 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-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 ドキュメントに 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> **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]]にあわせてください。 ただし、オラクルは、[[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 **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を組み立てる際に入力値をエスケープしてください。
タイムスタンプを変更しない
[[FAQ]] *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''~ S2Daoの開発の中で、updateBatchを投げる際、更新したくない列を指定~ したいのですが、方法がわかりません。~ ~ ''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''~ 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''~ 原因は 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''~ ~ S2DAO、S2JDBC等でSQLを発行する際にコンパイル済みのSQLを発行するのか、~ 毎SQLを生成して発行するのか、どちらなのでしょう?サンプルのログをみてい~ ると毎回生成しているように思えるのですが。。。~ ~ ''Answer''~ ~ PreparedStatementに格納してあるプリコンパイルされたSQLを発行しています。~ ~ ログではき出されているSQLは、Statementに渡される(発行する)SQLを~ そのまま表示している訳ではなく、ログにはき出すためにS2が、パラメータが~ 埋め込まれたSQLをせっせと作っています。~ ~ org.seasar.extension.jdbc.impl.BasicHandlerクラスの~ getCompleteSqlメソッドが参考になると思います。~ 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''~ ~ 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''~ ~ 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文の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''~ j2ee.diconでの設定を利用すれば自動的に1個のコネクションを得られます。~ 複数DBとのコネクションを取得するにはどうすればよいのでしょうか。~ ~ ''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/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''~ 複雑なSQLを処理する場合の実装方法について教え頂けませんでしょうか?~ ~ ''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~ // **幾何データ演算子を使いたい [#u7f14c3b] >[[S2サポーター]] (2006-04-29 (土) 18:45:30)~ ~ ''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''~ 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-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 ドキュメントに 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> **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]]にあわせてください。 ただし、オラクルは、[[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 **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を組み立てる際に入力値をエスケープしてください。
テキスト整形のルールを表示する