# SQLファイルを使用したDBアクセス

# SqlConfigの生成

SQLファイルを使用したサンプルコード SqlFileApiSample.java (opens new window) を例として説明します。

まず初めにコンストラクタの中で最初にSqlConfigクラスを作成しています。 SqlConfiguroboroSQLに対する各種の設定を保持するクラスで、SqlConfigの設定を変更することでuroboroSQLの動作を変更することが出来ます。
ここではH2DB (opens new window)のメモリDBに接続するSqlConfigインスタンスを生成しています。 SqlConfigの生成にはUroboroSQLクラスによるBuilderAPIを使用します。

  • 基本的な呼出方法(DBへの接続情報のみ指定)
// create SqlConfig
SqlConfig config = UroboroSQL.builder("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1", "sa", "").build();
1
2
  • 設定のカスタマイズ(定数の指定や検索結果の取得方法変更)
// create SqlConfig
SqlConfig config = UroboroSQL
    .builder("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1", "sa", "")
    // SqlContextFactoryの設定(Enum定数パッケージ設定の追加)
    .setSqlContextFactory(new SqlContextFactoryImpl()
    .setEnumConstantPackageNames(Arrays.asList(Gender.class.getPackage().getName())))
    // SqlAgentFactoryの設定(Queryの戻り値のMapのキー文字列のデフォルトCaseFormat設定の追加)
    .setSqlAgentFactory(new SqlAgentFactoryImpl().setDefaultMapKeyCaseFormat(CaseFormat.CAMEL_CASE))
    // SqlManagerの設定(NioSqlManagerImplの指定)
    .setSqlManager(new NioSqlManagerImpl(false))
    .build();
1
2
3
4
5
6
7
8
9
10
11

SqlConfig生成時のカスタマイズの詳細については 設定を参照してください。

# テーブルの作成と初期データの登録

次に事前準備として以降の処理で使用するテーブルの作成と初期データの登録を行います。(SqlFileApiSample#setupTableAndData()を参照)
SQLを実行する場合はSqlConfigからSqlAgentを生成します。 SqlAgenturoboroSQLの中核となるクラスで、uroboroSQLの各操作はこのSqlAgentを使って行います。
SqlAgentAutoClosableインタフェースを実装しているので、try-with-resources文で囲むことで処理終了時に自動でクローズされます。 このときSqlAgentの中に保持するConnectionStatementも合わせてクローズされるため、クローズ漏れによるメモリリークを防ぐことができます。

// create SqlAgent. SqlAgent implements AutoClosable.
try (SqlAgent agent = config.agent()) {
  // ここにSQL実行の処理を実装する
}
1
2
3
4

TIP

以降の説明ではSqlAgentに対する処理はtry-with-resources文の中で行っているものとします。

uroboroSQLでは実行するSQLをファイルパスに似た表現(以降 SQL名 と呼ぶ)で指定します。 下の例ではクラスパス上にあるsqlフォルダ配下のddl/create_tables.sqlを指定してSQL更新処理を実行します。

更新処理を行う場合、SqlAgent#update("[SQL名]")メソッドを使用してSqlUpdateを取得しUpdateの実行を行います。

// create table :  テーブル作成
agent.update("ddl/create_tables").count();
// setup data : 初期データ挿入
agent.update("setup/insert_data").count();
1
2
3
4

ddl/create_tables.sqlで作成したテーブルの構成は以下になります。

# SQLファイルを使用した検索

登録したデータを検索します。検索を行う際は、SqlAgent#query("[SQL名]")メソッドを使用してSqlQueryを取得し、バインドパラメータの設定や検索の実行を行います。

SqlQueryでは検索結果をいくつかの形式で取得することができます。

メソッド 説明
SqlQuery#collect() 検索結果をList<Map>の形式で取得する
SqlQuery#stream() 検索結果をjava.util.Streamの形式で取得する
SqlQuery#resultSet() 検索結果のResultSetを取得する
SqlQuery#first() 検索結果の1件目を取得する。取得できない場合はRuntimeExceptionがスローされる
SqlQuery#findFirst() 検索結果の1件目を取得する。戻り値はOptional
SqlQuery#one() 検索結果の1件目を取得する。取得できない場合、もしくは2件以上取得出来た場合はRuntimeExceptionがスローされる
SqlQuery#findOne() 検索結果の1件目を取得する。戻り値はOptional。2件以上取得出来た場合はRuntimeExceptionがスローされる

以下のように呼び出します。

// no parameter : バインドパラメータ指定なしで検索
List<Map<String, Object>> deps1 = agent.query("department/select_department")
    .collect();

// add bind parameter : バインドパラメータを設定して検索
List<Map<String, Object>> deps2 = agent.query("department/select_department")
    .param("deptNo", 1)
    .collect();
1
2
3
4
5
6
7
8

ここで実行されるSQLは以下のようになっています。

  • department/select_department.sql
select /* _SQL_ID_ */
    dept.dept_no        as    dept_no
,   dept.dept_name      as    dept_name
,   dept.lock_version   as    lock_version
from
    department    dept
/*BEGIN*/
where
/*IF SF.isNotEmpty(deptNo)*/
and dept.dept_no    = /*deptNo*/1
/*END*/
/*IF SF.isNotEmpty(deptName)*/
and dept.dept_name  = /*deptName*/'sample'
/*END*/
/*END*/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  • /* _SQL_ID_ */ はSQLを特定するID(SQL_IDといいます)を付与するための予約語で、実行時にSQLファイルを特定するための文字列に変換されます。
  • /*IF*/ ... /*END*/は条件分岐で、IFの後ろの評価式がTrueとなる場合に/*IF*//*END*/で囲まれた部分が出力されます。
  • /*deptNo*/はバインドパラメータで、実行時に?に変換され、SqlQueryに設定したパラメータがSQLへバインドされます。
  • /*deptNo*/の後ろの1はテスト用データです。このようにテスト用データをSQL文に記述しておくことで、このSQLを SQLクライアントツールで実行する際にエラーにならずに文法の確認を行うことができます。

SQLで使用できる構文については2WaySQLを参照してください。
また、検索のより詳しい説明はSQLによる検索を参照してください。

# SQLファイルを使用した行挿入

テーブルに対して行挿入を行うことも出来ます。 行挿入を行う際は、SqlAgent#update("[SQL名]")メソッドを使用してSqlUpdateを取得し、続けてバインドパラメータの設定やSQLの実行を行います。

agent.update("department/insert_department")
    .param("deptName", "production")
    .count();
1
2
3

ここで実行されるSQLは以下のようになっています。

  • department/insert_department.sql
insert /* _SQL_ID_ */
into
    department
(
    dept_name
,   lock_version
) values (
    /*deptName*/'sample'
,   0
)
1
2
3
4
5
6
7
8
9
10

SqlAgent#update("[SQL名]")では実行するSQLの内容によって行挿入の他に行更新や行削除を行うことが出来ます。より詳しい説明はSQLによる更新を参照してください。