ここまでの例ではscalikejdbcGenで自動生成されたメソッドや単一テーブルに対するシンプルなQueryDSLで処理できる例ばかりでしたが、ここではもう少し実践的な検索処理の実装方法について紹介します。
INNER JOIN
INNER JOINの場合はシンプルにinnerJoin
メソッドを使用します。検索結果の取得もシンプルです。以下の例ではUSERS
テーブルとCOMPANIES
テーブルをINNER JOINし、検索結果をそれぞれのモデルクラスのタプルのシーケンスで取得しています。
val users: Seq[(Users, Companies)] = withSQL {
select.from(Users as u).innerJoin(Companies as c).on(u.companyId, c.id)
}.map { rs =>
(Users(u)(rs), Companies(c)(rs))
}.list.apply()
LEFT JOIN
LEFT JOINの場合はleftJoin
メソッドを使用します。
val users: Seq[(Users, Option[Companies])] = withSQL {
select.from(Users as u).leftJoin(Companies as c).on(u.companyId, c.id)
}.map { rs =>
(Users(u)(rs), rs.intOpt(c.resultName.id).map(_ => Companies(c)(rs)))
}.list.apply()
LEFT JOINしたテーブルの値を取得する場合、map()
メソッドでOption
型に変換する必要があるという点に注意してください。以下のコードは、まず結果セットからCOMPANIES
テーブルのID
カラムをintOpt
メソッドでOption[Int]
型として取得し、値が取得できた場合のみCompanies
クラスにマッピングするという処理を行っています。
rs.intOpt(c.resultName.id).map(_ => Companies(c)(rs))
SQLを直接記述する
sql
interpolationを使うと文字列リテラルで生SQLを記述することができます。ただし、SQLを完全に記述するだけでなく、自動生成されたクラスを使って記述を補助することができます。
val users: Seq[(Users, Companies)] = sql"""
|SELECT ${u.result.*}, ${c.result.*}
|FROM ${Users.as(u)} INNER JOIN ${Companies.as(c)}
|ON ${u.companyId} = ${c.id}
""".stripMargin.map { rs =>
(Users(u)(rs), Companies(c)(rs))
}.list.apply()
SELECT句に大量のカラムを記述する必要がなかったり、テーブル名やカラム名のタイプミスを防ぐことができます。また、sql
interpolationを使う場合はwithSQL { ... }
で囲む必要はありません。map()
メソッド以降はQueryDSLの場合と同じです。
参考資料
ScalikeJDBCの詳細については以下のドキュメントが参考になります。