Javaアプリケーションでデータアクセス用のフレームワークとして、Mirage-SQLを使ってみたので、基本的な使い方を紹介します。
※プロジェクト管理ツールはMavenを使っています。
Mavenの設定
<dependency>
<groupId>jp.sf.amateras.mirage</groupId>
<artifactId>mirage</artifactId>
<version>***</version>
</dependency>
リポジトリも追加します。
<repository>
<id>amateras</id>
<name>amateras</name>
<url>http://amateras.sourceforge.jp/mvn</url>
</repository>
DBへの接続設定
クラスパスのルートにjdbc.properties
ファイルを配置します。
jdbc.driver=ドライバクラス
jdbc.url=URL
jdbc.user=ユーザ名
jdbc.password=パスワード
SQLファイル
クラスパスのルートに.sql
ファイルを配置します。
SELECT *
FROM staff
/*BEGIN*/
WHERE
/*IF username != null */
staffname = /*staffname*/'testuser'
/*END*/
/*IF staffstatus != null */
AND staffstatus = /*status*/1
/*END*/
/*END*/
意味ありげなコメントが挟まっています。
このコメント文とコメントの後ろの値がプリペアードステートメント生成時にプレースホルダに置き換わります。
バインド変数がSQLのコメントとして書かれており、その直後にテスト用の値が書かれているので、このSQLをDB管理ツールやコマンドラインでそのまま実行することができます。
これが「2WaySQL」です。
一般的に、アプリケーションからデータベースを操作する場合、SQLを文字列型の変数に格納して実行すると思いますが、Mirage-SQLを使うと、JavaのソースコードからSQLを完全に分離することができるので「実行してみるまでSQLの確認ができない」という状況を回避できます。
SQL文の組み立てを動的に行わないので、SQLインジェクション対策にもなります。
/*BEGIN*/〜/*END*/
については、構文エラーにならないように調整してくれるもの、と捉えておくとよいと思います。
(詳しくはgithubのwikiを参照してください)
Entityクラス
import jp.sf.amateras.mirage.annotation.Column;
import jp.sf.amateras.mirage.annotation.Table;
@Table(name = "staff")//クラス名とテーブル名が同じ場合は省略可
public class Staff implements Serializable {
@Column(name = "staffname")//カラム名とフィールド名が同じ場合は省略可
private String staffname ;
@Column(name = "staffstatus ")
private int staffstatus ;
//以下、アクセサメソッド
public void setStaffname (String staffname) {
this.staffname= staffname;
}
public String getStaffname () {
return staffname;
}
public void setStaffstatus (int staffstatus ) {
this.staffstatus = staffstatus ;
}
public int getStaffstatus () {
return staffstatus ;
}
}
データ取得
Session session = SessionFactory.getSession();
SqlManager sqlManager = session.getSqlManager();
session.begin();
try {
Map<String, Object> params = new HashMap<>();
params.put("status", 0);
SqlResource selectUserSql = new ClasspathSqlResource("test.sql");
List<Staff> results = sqlManager.getResultList(Staff.class, selectUserSql, params);
for (Staff result : results ) {
System.out.println(result.getStaffname());
}
session.commit();
} catch (Exception ex) {
session.rollback();
} finally {
session.release();
}
バインド変数に渡す値にMapを使いましたが、バインド変数と同名のフィールドを持つクラスでも大丈夫です。
※本記事はgithubを参考にしています。