« Apache Wicketを使ってみる | トップページ | Apache Wicketを使ってみる[3] -Model編- »

2019年9月 2日 (月)

続:Apache Wicketを使ってみる -データアクセス編-

0. データアクセスをどうするか

Quick Start Wizardで作成したMavenプロジェクトには、当然のことながらデータアクセスに関するライブラリがないので、自力でどうにかするしかない。

とはいえ、Spring Bootのような至れり尽くせりな環境でもないけど、ローレベルなJDBCをスクラッチで書き起こす元気もないので、今回はsql2oというライブラリを使ってみることにする。

1. sql2oとは

sql2o本家、およびGitHubの記述をざっくりまとめると、こんな感じ。

位置づけ的にはDapper.NETRoom Persisitence Libraryに近いかも。

  • 小さく軽量なデータアクセス用ライブラリ
  • JDBCのResultSetをPOJOに変換する機能を提供するが、SQLを生成する機能はない
  • 他の著名なライブラリに比べ、高速に(モノによっては6,7倍高速)動作する

導入はMavenで。執筆時点の最新版は1.6.0だった。
今回はDBMSにMySQLを使ってみることにするので、Connector/Jも一緒に設定しておく。

<dependency>
  <groupId>org.sql2o</groupId>
  <artifactId>sql2o</artifactId>
  <version>1.6.0</version>
</dependency>
<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>8.0.17</version>
</dependency>

2. 検索系処理

データベースへの接続は、Sql2oのコンストラクタに接続文字列を渡すことで作ってくれる。
なお、あえてすべてKotlinで書いてみた。

val database: Sql2o = Sql2o("jdbc:mysql://localhost:3306/mydb", "mydbadmin", "mydbadmin")

オープン処理とかは、DAOの基底クラスにプロパティを書いておくと扱いやすいかも。

/** トランザクションなしのConnection */
val connection: Connection
    get() {
        return database.open()
    }
/** トランザクション開始ありのConnection */
val connectionWithTran: Connection
    get() {
database.beginTransaction() }

で、検索系はSQLをそのまま書き、それを Connection#createQuery(String) に渡して Query オブジェクトを作り、 Query#executeAndFetch(Class) を実行すると ResultSet を POJO へバインドしてくれる。

// SQLをそのまま書く。長いSQLの場合はヒアドキュメントを使うと楽かも
val sql = "select todo_id, todo_title, created_at, finished from todo"
// 接続をオープン
val conn = connection
try {
    // use 関数でクエリ実行(Javaでいうところのtry-with-resources)
    conn.use {
        // setAutoDeriveColumnNames はスネークケース→キャメルケースを自動変換する設定
        val query = conn.createQuery(sql).setAutoDeriveColumnNames(true)
        val ret: MutableList<ToDo> = query.executeAndFetch(ToDo::class.java)
    }
} catch (e: Exception) {
    // do something...
}

3. 更新系処理

更新系処理も、検索系処理同様 createQuery(String) でプリペアードステートメントを作り、 Connection#executeUpdate() で実行する。

val sql = "insert into todo (todo_title, created_at, finished) values (:todoTitle, :createdAt, :finished)"
// トランザクション開始ありのConnectionを取得
val tran = connectionWithTran
try {
    tran.use {
        val stmt = tran.createQuery(sql)
                // プリペアードステートメントへバインドするパラメータを追加していく
                .addParameter("todoTitle", todo.todoTitle)
                .addParameter("createdAt", todo.createdAt)
                .addParameter("finished", todo.finished)
        stmt.executeUpdate()
        // use 関数内で commit()を発行
        tran.commit()
    }
} catch (e: Exception) {
    // do something...
    // ロールバックは暗黙的に行われる
}

なお、sql2oには宣言的トランザクションはないので、トランザクション制御は自分でやらなければならない。

4. 最後に

自力でSQLのチューニングをしたほうが手っ取り早い場合なんかには、こういうライブラリのほうがいいかもしれない。

|

« Apache Wicketを使ってみる | トップページ | Apache Wicketを使ってみる[3] -Model編- »

コメント

コメントを書く



(ウェブ上には掲載しません)




« Apache Wicketを使ってみる | トップページ | Apache Wicketを使ってみる[3] -Model編- »