S2Dao譲りのSQLファイル
S2Dao譲りのSQLファイルを使うこともできます。
SQLファイルとは、SQLをソースコードに記述するのではなく、 ファイルに記述したものです。 単純なSQLだとソースコードに直接記述したほうが、 めんどくさくなくて楽(わざわざファイルを作る必要がない)ですが、 複雑なSQLは、ファイルに記述したほうが、メンテナンスがしやすくなります。
SQLファイルは、クラスパス上にあるならどこにおいてもかまいませんが、
ルートパッケージ.entity.エンティティ名
のパッケージに対応したディレクトリ配下に置くことを推奨します。 例えば、
Employeeに関するSQLファイルは、
examples/entity/Employee
ディレクトリにおくと良いでしょう。
SQLファイルのエンコーディングはUTF-8のみをサポートしています。
複数のテーブルを結合するような場合は、 一番主軸となっているテーブルを選びます。 プロシージャやファンクションの場合も同様です。
何のパラメータもない単純なSQLファイルは次のようになります。
select * from employee where salary >= 1000 and salary <= 2000
1000の部分を
salaryMin
というパラメータで置き換えるには、
次のように置き換えたいリテラルの左にSQLコメントでパラメータ名を埋め込みます。
リテラルを文字列として直接置き換えるのではなく、
PreparedStatment
を使ったバインド変数に置き換えるので、SQLインジェクション対策も問題ありません。
select * from employee where salary >= /*salaryMin*/1000 and salary <= 2000
同様に2000の部分も
salaryMax
というパラメータで置き換えます。
select * from employee where salary >= /*salaryMin*/1000 and salary <= /*salaryMax*/2000
in
を置き換える場合は次のようにします。 ()で囲まれている部分を置き換えます。
idのパラメータの型は、配列かリストになります。
select * from employee where id in /*id*/(1, 2)
like
を置き換える場合は次のようにします。 '(シングルクオート)で囲まれている部分を置き換えます。
ワイルドカードを使いたい場合は、パラメータの値に埋め込んでください。
select * from employee where name like /*name*/'S%'
検索条件の入力画面などによくあるパターンで、何か条件が入力されていれば、 検索条件に追加し、入力されていなければ条件には追加しないということを実装してみましょう。 このような場合は、IFコメントとENDコメントを組み合わせます。
select * from employee where /*IF salaryMin != null*/ salary >= /*salaryMin*/1000 /*END*/ /*IF salaryMax != null*/ and salary <= /*salaryMax*/2000 /*END*/
IFコメントの内容が
true
なら、 IFコメントとENDコメントで囲んでいる内容が出力されます。
IFコメントの条件は、OGNLによって評価されます。 詳しくは、
OGNLガイド
を参照してください。
上記のように記述すると、salaryMinがnullではなくて、 salaryMaxがnullのときには、 下記のように正しいSQLになります。
select * from employee where salary >= ?
しかしsalaryMinがnullでsalaryMaxがnullではないときは、 次のような不正(andがwhereの直後にある)なSQLになります。
select * from employee where and salary <= ?
また、salaryMinとsalaryMaxがnullの場合も、 次のような不正(whereだけがある)なSQLになります。
select * from employee where
この問題に対応するためには、where句の部分を次のように、 BEGINコメントとENDコメントで囲みます。
select * from employee /*BEGIN*/ where /*IF salaryMin != null*/ salary >= /*salaryMin*/1000 /*END*/ /*IF salaryMax != null*/ and salary <= /*salaryMax*/2000 /*END*/ /*END*/
このようにすると、salaryMinがnullでsalaryMaxがnullではないときは、
salaryMaxの条件は、BEGINコメントとENDコメントで囲まれた最初の条件なので、
and
の部分が自動的に削除されて次のようになります。
select * from employee where salary <= ?
また、salaryMinとsalaryMaxがnullの場合は、 BEGINコメントとENDコメントで囲まれた部分に有効なIFコメントが一つもないため、 BEGINコメントとENDコメントで囲まれた全体がカットされて次のようになります。
select * from employee
バインド変数ではなく、SQLに直接リテラルを埋め込むには、 埋め込み変数コメントを使います。
埋め込み変数コメントは、/*$パラメータ名*/のように指定します。
直接リテラルを埋め込むとSQLインジェクションの危険がありますが、
埋め込み変数の値に、セミコロン(;)が入っていると例外にしているので、 問題はありません。
order by
句をパラメータで変えたい場合は、 /*$orderBy*/と指定します。
select * from employee order by /*$orderBy*/id
ELSEコメントは、IFコメントとENDコメントの間に行コメントとして埋め込みます。
/*IF jobType != null*/ jobType = /*jobType*/'CLERK' -- ELSE jobType is null /*END*/
SQLファイルのパス
SQLファイルのパスは、
examples/sql/employee/selectAll.sql
のように指定します。 このパスに対するデフォルトの物理的なファイルは、 そのまま
examples/sql/employee/selectAll.sql
になります。 ただし、
ダイアレクト
のサフィックスに対応するファイルがあれば、 そちらが優先されます。
例えば、オラクルを使っている場合、
examples/sql/employee/selectAll_oracle.sql
があれば、デフォルトより優先されます。
検索
複数件検索
SQLファイルを使って複数件検索をする場合は、
selectBySqlFile()
と
getResultList()
を組み合わせます。
selectBySqlFile()
の2番目の引数は、
SQLファイルのパス
です。
SQLファイルにパラメータがない場合は、次のようにして呼び出します。
List<EmployeeDto> results = jdbcManager .selectBySqlFile( EmployeeDto.class, "examples/sql/employee/selectAll.sql") .getResultList();
SQLファイルのパラメータが1つの場合は、
selectBySqlFile()
の3番目の引数で値を直接指定します。
SQLファイルの中では/*$1*/のようにパラメータを指定してください。
List<EmployeeDto> results = jdbcManager .selectBySqlFile( EmployeeDto.class, "examples/sql/employee/selectAll.sql", 10) .getResultList();
SQLファイルのパラメータが複数の場合は、
selectBySqlFile()
の3番目の引数をJavaBeansまたは
Map<String, Object>
にして、
パラメータの名前とJavaBeansのプロパティ名または
Map
のキーを一致させます。
package examples.entity.Employee; public class SelectAllParam { public BigDecimal salaryMin; public BigDecimal salaryMax; }
select * from employee where salary <= /*salaryMin*/1000 and salary >= /*salaryMax*/2000
SelectAllParam param = new SelectAllParam(); param.salaryMin = new BigDecimal(1200); param.salaryMax = new BigDecimal(1800); List<EmployeeDto> results = jdbcManager .selectBySqlFile( EmployeeDto.class, "examples/sql/employee/selectAll.sql", param) .getResultList();
Mapを使うと次のようになります。
PostgreSQLの場合、引数に
Map
を使用すると、
String
以外の型の値に
null
を指定することは出来ません。
パラメータに
null
を指定する必要がある場合はDtoを使用してください。
Map<String, Object> param = new HashMap<String, Object>(); param.put("salaryMin", new BigDecimal(1200)); param.put("salaryMax", new BigDecimal(1800)); List<EmployeeDto> results = jdbcManager .selectBySqlFile( EmployeeDto.class, "examples/sql/employee/selectAll.sql", param) .getResultList();
org.seasar.extension.jdbc.parameter.Parameter
のstaticメソッドを使うと、流れるようなインタフェースでMapを組み立てることも出来ます。
import static org.seasar.extension.jdbc.parameter.Parameter.*; List<EmployeeDto> results = jdbcManager .selectBySqlFile( EmployeeDto.class, "examples/sql/employee/selectAll.sql", params("salaryMin", new BigDecimal(1200)) .$("salaryMax", new BigDecimal(1800)) .$()) .getResultList();
Map
で
java.util.Date
・
java.util.Calendar
型のパラメータを指定する場合は、時制を指定することができます。 時制の指定は
org.seasar.extension.jdbc.parameter.Parameter
のstaticメソッドを使います。
date(Date)
またはdate(Calendar)
- パラメータをSQL標準のDATE型 (日付のみ) として扱います。
time(Date)
またはtime(Calendar)
- パラメータをSQL標準のTIME型 (時刻のみ) として扱います。
timestamp(Date)
またはtimestamp(Calendar)
- パラメータをSQL標準のTIMESTAMP型 (日付と時刻) として扱います。
select * from employee where heredate <= /*heredate*/'2000/04/01'
import static org.seasar.extension.jdbc.parameter.Parameter.*; List<EmployeeDto> results = jdbcManager .selectBySqlFile( EmployeeDto.class, "examples/sql/employee/selectAll.sql", params("heredate", date(heredate)) //heredateはjava.util.Date型 .$())) .getResultList();
Map
で
byte[]
・
String
型のパラメータを指定する場合は、ラージオブジェクトであることを指定することができます。
ラージオブジェクトの指定は
org.seasar.extension.jdbc.parameter.Parameter
のstaticメソッドを使います。
lob(String)
- パラメータをCLOBとして扱います。
lob(byte[])
またはlob(Serializable)
- パラメータをBLOBとして扱います。
select * from employee where largeName <= /*largeName*/'hoge'
import static org.seasar.extension.jdbc.parameter.Parameter.*; List<EmployeeDto> results = jdbcManager .selectBySqlFile( EmployeeDto.class, "examples/sql/employee/selectAll.sql", params("largeName", lob(largeName)) //largeNameはCLOB型 .$()) .getResultList();
パラメータ用のJavaBeansまたは
Map
にlimit、offsetという名前のプロパティまたはキーがあれば、
ページングが行なわれます。
limit, offsetはパラメータの予約語なので注意してください。
結果を
Map
で受け取ることもできます。
List<BeanMap> results = jdbcManager .selectBySqlFile( BeanMap.class, "examples/sql/employee/selectAll.sql") .getResultList();
BeanMapはMap<String, Object>なクラスで、 存在しないキーにアクセスすると 例外が発生します。 キーの値は、AAA_BBBのような'_'記法の値ををaaaBbbのようなキャメル記法に 変換したものです。
このルールは、convention.diconで指定されている
org.seasar.framework.convention.impl.PersistenceNamingConventionImpl
のfromColumnNameToPropertyName()の実装を変えることで、カスタマイズすることができます。
デフォルトでは、結果がなかった場合は、 空の
List
が返されます。
disallowNoResult()
を呼び出すと、 結果がなかった場合は
javax.persistence.NoResultException
が発生します。
List<BeanMap> results = jdbcManager .selectBySqlFile( BeanMap.class, "examples/sql/employee/selectAll.sql") .disallowNoResult() .getResultList();
1件検索
SQLファイルを使って1件検索をする場合は、
selectBySqlFile()
と
getSingleResult()
を組み合わせます。
selectBySqlFile()
の2番目の引数は、
SQLファイルのパス
です。
SQLファイルにパラメータがない場合は、次のようにして呼び出します。
EmployeeDto result = jdbcManager .selectBySqlFile( EmployeeDto.class, "examples/sql/employee/selectSingle.sql") .getSingleResult();
SQLファイルのパラメータが1つの場合は、
selectBySqlFile()
の3番目の引数で値を直接指定します。
EmployeeDto result = jdbcManager .selectBySqlFile( EmployeeDto.class, "examples/sql/employee/selectSingle.sql", 10) .getSingleResult();
SQLファイルのパラメータが複数の場合は、
selectBySqlFile()
の3番目の引数をJavaBeansにして、
パラメータの名前とJavaBeansのプロパティ名を一致させます。
パラメータ用のJavaBeansにlimit、offsetという名前のプロパティがあれば、 ページングが行なわれます。
limit, offsetはパラメータ用のJavaBeansのプロパティの予約語なので注意してください。
結果を
Map
で受け取ることもできます。
BeanMap result = jdbcManager .selectBySqlFile( BeanMap.class, "examples/sql/employee/selectSingle.sql") .getSingleResult();
BeanMapはMap<String, Object>なクラスで、 存在しないキーにアクセスすると 例外が発生します。 キーの値は、AAA_BBBのような'_'記法の値ををaaaBbbのようなキャメル記法に 変換したものです。
このルールは、convention.diconで指定されている
org.seasar.framework.convention.impl.PersistenceNamingConventionImpl
のfromColumnNameToPropertyName()の実装を変えることで、カスタマイズすることができます。
デフォルトでは、結果がなかった場合は、
null
が返されます。
disallowNoResult()
を呼び出すと、 結果がなかった場合は
javax.persistence.NoResultException
が発生します。
BeanMap result = jdbcManager .selectBySqlFile( BeanMap.class, "examples/sql/employee/selectSingle.sql") .disallowNoResult() .getSingleResult();
イテレーションによる検索
検索結果が多くの行を返すため、
List
でまとめて受け取ることが困難な場合は
iterate(IterationCallback)
を使います。
int results = jdbcManager .selectBySqlFile( EmployeeDto.class, "examples/sql/employee/selectAll.sql") .iterate( new IterationCallback<EmployeeDto, Integer>() { int count; public Integer iterate(EmployeeDto dto, IterationContext context) { if (...) { ++count; } return count; } });
iterate(IterationCallback)
の引数には、 次のインターフェースを実装したクラスのインスタンスを渡します。
org.seasar.extension.jdbc.IterationCallback<ENTITY, RESULT>
ENTITY
は
selectBySqlFile()
で指定したクラス、
RESULT
は
iterate(IterationCallback)
が返す結果の型を指定します。
問い合わせ結果の1行ごとに次のメソッドがコールバックされます。
RESULT iterate(ENTITY entity, IterationContext context)
コールバックメソッドが最後に返した値が
iterate(IterationCallback)
の戻り値となります。
コールバックメソッドの第2引数で渡される
org.seasar.extension.jdbc.IterationContext
の
exit
プロパティを
true
にすると、 問い合わせ結果のイテレーションは終了となり、 検索結果の残りは無視されます。
その時の戻り値が
iterate(IterationCallback)
の戻り値となります。
検索結果の行数取得
SELECT COUNT(*) ~による検索結果の行数を取得する場合は、getCountBySqlFile()を使います。
long count = jdbcManager .getCountBySqlFile(examples/sql/employee/selectAll.sql);
このメソッドは通常、
select count(*) from (
SQL
)
を 実行した結果を返します。
SQLファイルのパラメータが複数の場合は、
getCountBySqlFile()
の3番目の引数をJavaBeansにして、
パラメータの名前とJavaBeansのプロパティ名を一致させます。
ページング
ページングを指定する場合は、
limit(), offset()
を使います。
limit()
には、取得する行数を指定します。
offset()
には、最初に取得する行の位置を指定します。 最初の行の位置は0になります。
ページングを指定するには、必ず
ordey by
句が必要です。 order by句で指定するカラムは、selectリストにも含めるようにしてください。
select id, name, ... from employee order by name
jdbcManager .selectBySqlFile( EmployeeDto.class, "examples/sql/employee/selectAll.sql") .limit(100) .offset(10) .getResultList();
挿入・更新・削除
1件挿入・更新・削除
SQLファイルを使ってエンティティを更新する場合は、
updateBySqlFile()
、
execute()
を組み合わせます。 挿入、削除も
updateBySqlFile()
を使います。
SQLファイルにパラメータがない場合は、次のようにして呼び出します。
int count = jdbcManager .updateBySqlFile("examples/sql/employee/update.sql") .execute();
SQLファイルのパラメータが1つで値が
null
にならない場合は、
updateBySqlFile()
の2番目の引数で値を直接指定します。
int count = jdbcManager .updateBySqlFile( "examples/sql/employee/update.sql", 10) .execute();
上記以外の場合は、
updateBySqlFile()
の2番目の引数をJavaBeansまたは
Map<String, Object>
にして、
パラメータの名前とJavaBeansのプロパティ名または
Map
のキーを一致させます。
package examples.entity.Employee; public class UpdateParam { public Integer id; public BigDecimal salary; }
update emp set salary = /*salary*/1000 where id = /*id*/1
UpdateParam param = new UpdateParam(); param.salary = new BigDecimal(1200); param.id = 10; int count = jdbcManager .updateBySqlFile( "examples/sql/employee/update.sql", param) .execute();
Mapを使うと次のようになります。
PostgreSQLの場合、引数に
Map
を使用すると、
String
以外の型の値に
null
を指定することは出来ません。
パラメータに
null
を指定する必要がある場合はDtoを使用してください。
Map<String, Object> param = new HashMap<String, Object>(); param.put("salary", new BigDecimal(1200)); param.id = 10; int count = jdbcManager .updateBySqlFile( "examples/sql/employee/update.sql", param) .execute();
org.seasar.extension.jdbc.parameter.Parameter
のstaticメソッドを使うと、流れるようなインタフェースでMapを組み立てることも出来ます。
import static org.seasar.extension.jdbc.parameter.Parameter.*; int count = jdbcManager .updateBySqlFile( "examples/sql/employee/update.sql", params("salary", new BigDecimal(1200) .$()); .execute();
Map
で
java.util.Date
・
java.util.Calendar
型のパラメータを指定する場合は、時制を指定することができます。 時制の指定は
org.seasar.extension.jdbc.parameter.Parameter
のstaticメソッドを使います。
date(Date)
またはdate(Calendar)
- パラメータをSQL標準のDATE型 (日付のみ) として扱います。
time(Date)
またはtime(Calendar)
- パラメータをSQL標準のTIME型 (時刻のみ) として扱います。
timestamp(Date)
またはtimestamp(Calendar)
- パラメータをSQL標準のTIMESTAMP型 (日付と時刻) として扱います。
update emp set salary = /*salary*/1000 where heredate <= /*heredate*/'2000/04/01'
import static org.seasar.extension.jdbc.parameter.Parameter.*; int count = jdbcManager .updateBySqlFile( "examples/sql/employee/update.sql", params("heredate", date(heredate)) //heredateはjava.util.Date型 .$()) .execute();
Map
で
byte[]
・
String
型のパラメータを指定する場合は、ラージオブジェクトであることを指定することができます。
ラージオブジェクトの指定は
org.seasar.extension.jdbc.parameter.Parameter
のstaticメソッドを使います。
lob(String)
- パラメータをCLOBとして扱います。
lob(byte[])
またはlob(Serializable)
- パラメータをBLOBとして扱います。
update emp set salary = /*salary*/1000 where largeName <= /*largeName*/'hoge'
import static org.seasar.extension.jdbc.parameter.Parameter.*; int count = jdbcManager .updateBySqlFile( "examples/sql/employee/update.sql", params("largeName", lob(largeName)) //largeNameはCLOB型 .$()) .execute();
バッチ挿入・更新・削除
SQLファイルを使ってエンティティをバッチ更新する場合は、
updateBatchBySqlFile()
、
execute()
を組み合わせます。 挿入、削除も
updateBatchBySqlFile()
を使います。
SQLファイルのパラメータが1つで値が
null
にならない場合は、
updateBatchBySqlFile()
の2番目の引数で値のリストを指定します。
List<Integer> paramList = new ArrayList<Integer>(); ... int[] countArray = jdbcManager .updateBatchBySqlFile( "examples/sql/employee/update.sql", paramList) .execute();
上記以外の場合は、
updateBatchBySqlFile()
の2番目の引数をJavaBeansまたは
Map<String, Object>
のリストあるいは配列(可変長引数)にして、
パラメータの名前とJavaBeansのプロパティ名または
Map
のキーを一致させます。
バッチ更新で使用するSQLファイルでIFコメントや埋め込み変数コメントを使用する場合、 IFコメントや埋め込み変数コメントはリストまたは配列(可変長引数)の最初の要素だけで評価されます。 2番目以降の要素は、最初の要素で作成されたSQL文のバインド変数に適用されるだけで、 IFコメントや埋め込み変数コメントの評価には使われません。
リストや配列の要素ごとに異なったSQL文が使われるようにする必要がある場合は、 バッチ更新ではなく1件ずつの更新を使用してください。
IFコメントや埋め込み変数コメントを含むSQLファイルを間違ってバッチ更新で使ってしまった場合に
速やかに検出するには、
s2jdbc.dicon
で、
JdbcManager
の
allowVariableSqlForBatchUpdate
プロパティを
false
に設定します。
s2jdbc.dicon
については「
セットアップ-概要
」を参照してください。
PostgreSQLの場合、引数に
Map
を使用すると、
String
以外の型の値に
null
を指定することは出来ません。
パラメータに
null
を指定する必要がある場合はDtoを使用してください。
package examples.entity.Employee; public class UpdateParam { public Integer id; public BigDecimal salary; }
update emp set salary = /*salary*/1000 where id = /*id*/1
List<UpdateParam> paramList = new ArrayList<UpdateParam>(); ... int[] countArray = jdbcManager .updateBatchBySqlFile( "examples/sql/employee/update.sql", paramList) .execute();
一意制約違反によりエンティティを挿入ができなかった場合は、
javax.persistence.EntityExistsException
が発生します。
Map
で
java.util.Date
・
java.util.Calendar
型のパラメータを指定する場合は、時制を指定することができます。 時制の指定は
org.seasar.extension.jdbc.parameter.Parameter
のstaticメソッドを使います。
date(Date)
またはdate(Calendar)
- パラメータをSQL標準のDATE型 (日付のみ) として扱います。
time(Date)
またはtime(Calendar)
- パラメータをSQL標準のTIME型 (時刻のみ) として扱います。
timestamp(Date)
またはtimestamp(Calendar)
- パラメータをSQL標準のTIMESTAMP型 (日付と時刻) として扱います。
Map
で
byte[]
・
String
型のパラメータを指定する場合は、ラージオブジェクトであることを指定することができます。
ラージオブジェクトの指定は
org.seasar.extension.jdbc.parameter.Parameter
のstaticメソッドを使います。
lob(String)
- パラメータをCLOBとして扱います。
lob(byte[])
またはlob(Serializable)
- パラメータをBLOBとして扱います。
バッチ更新のサイズを指定する
バッチ更新のサイズを設定するには
batchSize()
を使います。
List<UpdateParam> paramList = new ArrayList<UpdateParam>(); ... int[] countArray = jdbcManager .updateBatchBySqlFile( "examples/entity/Employee/update.sql", paramList) .batchSize(50) .execute();
一意制約違反によりエンティティを挿入ができなかった場合は、
javax.persistence.EntityExistsException
が発生します。
ストアドの呼び出し
ストアドプロシージャの呼び出し
SQLファイルを使ってストアドプロシージャを呼び出す場合は、
callBySqlFile()
と
execute()
を組み合わせます。
callBySqlFile()
の最初の引数は、
SQLファイルのパス
です。
最初の例は、パラメータのない場合です。
jdbcManager .callBySqlFile("examples/sql/employee/callMyProc.sql") .execute();
INのパラメータが1つだけで、そのパラメータが
null
にならない場合は、
callBySqlFile()
の2番目の引数で値を直接指定します。
jdbcManager .callBySqlFile( "examples/sql/employee/callMyProc.sql", "hoge") .execute();
上記以外の場合は、
callBySqlFile()
の2番目の引数にJavaBeansを指定します。
プロシージャを呼び出すパラメータの順番にJavaBeansのフィールドを定義します。
S2JDBCは、ソースコード上に記述したフィールドの順番と、 コンパイルされた.classファイル内のフィールドの順番が同じになることを前提としていますが、 これはJavaの仕様では保証されていません. SunのJDKやEclipseではソースコード上と.classファイル内のフィールド順は同じになっていますが、 フィールドの順番が変わってしまう環境ではストアドの呼び出しが失敗します。 フィールドの順番が変わってしまう環境があった場合は Seasar-userメーリングリスト までお知らせください.
-
フィールドにアノテーションが付けられていない場合、
IN
パラメータになります。 -
フィールドに
@Out
アノテーションが付けられている場合、OUT
パラメータになります。 -
フィールドに
@InOut
アノテーションが付けられている場合、INOUT
パラメータになります。 -
フィールドに
@ResultSet
アノテーションが付けられている場合、 パラメータ以外で戻される結果セットになります。 ただし、 OracleやPostgreSQLのように、 パラメータ以外で結果セットを返すことが出来ないRDBMSの場合は、OUT
パラメータとして扱われます。 -
フィールドに
@Lob
が付けられている場合、 そのパラメータはLOBとして扱われます。@Lob
アノテーションは他のアノテーションと組み合わせて使用することが出来ます。
public class MyDto { public String arg1; // 第1引数 (IN) @Out public String arg2; // 第2引数 (OUT) @InOut public int arg3; // 第3引数 (INOUT) @ResultSet public List<String> result; // 結果セット }
MyDto dto = new MyDto(); dto.arg1 = "hoge"; dto.arg3 = 2; jdbcManager .callBySqlFile( "examples/sql/employee/callMyProc.sql", dto) .execute(); System.out.println(dto.arg2); System.out.println(dto.arg3); System.out.println(dto.result);
ストアドプロシージャが複数のカラムを持つ結果セットを返す場合は、 対応するフィールドの型をList<結果セットの行に対応するJavaBeansの型>にします。
public class MyDto { public int arg1; // 第1引数 (IN) @ResultSet public List<EmployeeDto> result; // 結果セット }
MyDto dto = new MyDto(); dto.arg1 = 1; jdbcManager .callBySqlFile( "examples/sql/employee/callMyProc.sql", dto) .execute(); System.out.println(dto.result);
オラクルとPostgreSQLの場合は、結果セットをパラメータで受け取る必要があります。
これらのRDBMSでは、
@ResultSet
アノテーションが付けられたパラメータは
OUT
パラメータとして扱われるので、
ストアドプロシージャ呼び出しのSQLの中に対応するバインド変数を付け加えます。
public class MyDto { public int arg1; // 第1引数 (IN) @ResultSet public List<EmployeeDto> result; // 第2引数 (OUT) }
MyDto dto = new MyDto(); dto.arg1 = 1; jdbcManager .callBySql( "examples/sql/employee/callMyProc.sql", dto) .execute(); System.out.println(dto.result);
ストアドファンクションの呼び出し
SQLファイルを使ってストアドファンクションを呼び出す場合は、
callBySqlFile()
と、
getSingleResult()
または
getResultList()
を組み合わせます。
callBySqlFile()
の1番目の引数でストアドファンクションの戻り値の型を指定します。 2番目の引数は、
SQLファイルのパス
です。
最初の例はパラメータがなく、 戻り値が結果セットでない場合です。
String result = jdbcManager .callBySqlFile( String.class, "examples/sql/employee/callMyFunc.sql") .getSingleResult();
OracleやPostgreSQLのように、
ストアドファンクションの戻り値で結果セットを返すことが出来る場合は
getResultList()
で結果の
List
を受け取ります。
callBySqlFile()
の1番目の引数で
List
の要素の型を指定します。
List<String> result = jdbcManager .callBySqlFile( String.class, "examples/sql/employee/callMyFunc.sql") .getResultList();
結果セットの行が複数のカラムを持つ場合は
List
の要素をJavaBeansにします。
List<MyDto> result = jdbcManager .callBySqlFile( MyDto.class, "examples/sql/employee/callMyFunc.sql") .getResultList();
INのパラメータが1つだけで、そのパラメータが
null
にならない場合は、
callBySqlFile()
の3番目の引数で値を直接指定します。
String result = jdbcManager .callBySqlFile( String.class, "examples/sql/employee/callMyFunc.sql", "hoge") .getSingleResult();
上記以外の場合は、
callBySqlFile()
の3番目の引数にJavaBeansを指定します。
ストアドファンクションを呼び出すパラメータの順番にJavaBeansのフィールドを定義します。
S2JDBCは、ソースコード上に記述したフィールドの順番と、 コンパイルされた.classファイル内のフィールドの順番が同じになることを前提としていますが、 これはJavaの仕様では保証されていません. SunのJDKやEclipseではソースコード上と.classファイル内のフィールド順は同じになっていますが、 フィールドの順番が変わってしまう環境ではストアドの呼び出しが失敗します。 フィールドの順番が変わってしまう環境があった場合は Seasar-userメーリングリスト までお知らせください.
-
フィールドにアノテーションが付けられていない場合、
IN
パラメータになります。 -
フィールドに
@Out
アノテーションが付けられている場合、OUT
パラメータになります。 -
フィールドに
@InOut
アノテーションが付けられている場合、INOUT
パラメータになります。 -
フィールドに
@ResultSet
アノテーションが付けられている場合、 パラメータ以外で戻される結果セットになります。 ただし、 OracleやPostgreSQLのように、 パラメータ以外で結果セットを返すことが出来ないRDBMSの場合は、OUT
パラメータとして扱われます。 -
フィールドに
@Lob
が付けられている場合、 そのパラメータはLOBとして扱われます。@Lob
アノテーションは他のアノテーションと組み合わせて使用することが出来ます。
public class MyDto { public String arg1; // 第1引数 (IN) @Out public String arg2; // 第2引数 (OUT) @InOut public int arg3; // 第3引数 (INOUT) @ResultSet public List<String> result; // 結果セット }
MyDto dto = new MyDto(); dto.arg1 = "hoge"; dto.arg3 = 2; String result = jdbcManager .callBySqlFile( String.class, "examples/sql/employee/callMyFunc.sql", dto) .getSingleResult(); System.out.println(result); System.out.println(dto.arg1); System.out.println(dto.arg3); System.out.println(dto.result);
ストアドファンクションが複数のカラムを持つ結果セットを返す場合は、 対応するフィールドの型をList<結果セットの行に対応するJavaBeansの型>にします。
public class MyDto { public int arg1; // 第1引数 (IN) @ResultSet public List<EmployeeDto> result; // 結果セット }
MyDto dto = new MyDto(); dto.arg1 = 1; String result = jdbcManager .callBySqlFile( String.class, "examples/sql/employee/callMyFunc.sql", dto) .getSingleResult(); System.out.println(result); System.out.println(dto.result);
オラクルとPostgreSQLの場合は、戻り値以外の結果セットをパラメータで受け取る必要があります。
これらのRDBMSでは、
@ResultSet
アノテーションが付けられたパラメータは
OUT
パラメータとして扱われるので、
ストアドファンクション呼び出しのSQLの中に対応するバインド変数を付け加えます。
public class MyDto { public int arg1; // 第1引数 (IN) @ResultSet public List<EmployeeDto> result; // 第2引数 (OUT) }
MyDto dto = new MyDto(); dto.arg1 = 1; String result = jdbcManager .callBySqlFile( String.class, "examples/sql/employee/callMyFunc.sql", dto) .getSingleResult(); System.out.println(result); System.out.println(dto.result);