クエリを実行する
行をケースクラスに読み込みます。
「クエリを実行する」はCoddyKit上の無料Scala for Backend Engineering & Functional Programmingレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはScala for Backend Engineering & Functional Programming学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Scala for Backend Engineering & Functional Programmingコースには全4レッスンが含まれています。
sqlインターポレーター
Doobieのsql文字列インターポレーターは、クエリの中核です。SQLをパースし、埋め込まれたScalaの値を安全なバインドパラメーターに変換します。
インターポレートされた値はJDBCの?プレースホルダーになるため、SQLインジェクションが発生せず、PreparedStatementを手動で組み立てる必要もありません。
import doobie.implicits._
val minAge = 18
val frag = sql"select name from users where age >= $minAge"FragmentからQueryへ
sql"..."式はFragmentです。読み取りとして実行するには.query[A]を呼び出し、行の型Aを指定します。
DoobieはRead[A]型クラスを使って結果の列をAにマッピングします。プリミティブ型、タプル、ケースクラスに対応しています。
case class User(name: String, age: Int)
val q: Query0[User] =
sql"select name, age from users".query[User]unique、option、to
Query0[A]にはさまざまなアキュムレーターがあります。.uniqueは行がちょうど1件、.optionは0件または1件であることを想定し、.to[List]はすべての行を収集します。
いずれも、後から.transactするConnectionIOを返します。
val one: ConnectionIO[User] = q.unique
val maybe: ConnectionIO[Option[User]] = q.option
val all: ConnectionIO[List[User]] = q.to[List]行をケースクラスにマッピングする
各フィールドに列マッピングがあれば、Doobieはケースクラス用のReadインスタンスを自動的に導出します。列の順序はselectリストと一致している必要があります。
これにより、定型的な行の解析コードを書かずに、豊富なドメイン型へ直接selectできます。
case class Account(id: Long, email: String, active: Boolean)
val accounts =
sql"select id, email, active from accounts"
.query[Account].to[Vector]パラメーター化クエリ
補間されたScalaの値はすべて、そのPutインスタンスを使ってパラメーターとしてバインドされます。異なる位置を含め、いくつでも補間できます。
値は連結されずにバインドされるため、型がチェックされ、インジェクションも不可能です。
def findByEmail(email: String): ConnectionIO[Option[Account]] =
sql"select id, email, active from accounts where email = $email"
.query[Account].option大きな結果セットのストリーミング
大きな結果セットには.streamを使い、fs2のStream[ConnectionIO, A]を取得します。行はサーバー側カーソルで遅延的に読み取られるため、メモリ使用量を一定に保てます。
fs2のコンビネーターと組み合わせれば、数百万行も段階的に処理できます。
import fs2.Stream
val s: Stream[ConnectionIO, Account] =
sql"select id, email, active from accounts"
.query[Account].streamフェッチサイズの制御
一部のドライバーでは、デフォルトのカーソルフェッチサイズによってすべてのデータが一度に読み込まれることがあります。.streamWithChunkSize(n)はJDBCのフェッチサイズを設定し、カーソルが1回の往復でn行を取得するようにします。
これを調整することで、往復回数とメモリ使用量のバランスを取れます。
val s =
sql"select id, email, active from accounts"
.query[Account]
.streamWithChunkSize(512)オプション列とNULL可能性
NULL可能な列は、行の型ではOption[A]にマッピングします。列がNULLになり得る場合はOptionとして読み取る必要があり、そうしないとDoobieはNULL値で例外をスローします。
これにより、境界部分でNULL可能性を明示的かつ型安全に扱えます。
case class Person(id: Long, nickname: Option[String])
val ps =
sql"select id, nickname from people".query[Person].to[List]FragmentによるSQLの構築
Fragment値は++で合成できます。パラメーターをバインドしたまま、クエリを複数の部品から組み立てられます。
fr補間子は末尾にスペースがあるFragmentを構築するため、句をつなぎ合わせるときに便利です。
val base = fr"select id, email, active from accounts"
val where = fr"where active = $${true}"
val q = (base ++ where).query[Account]動的なWHERE句
DoobieのFragmentsヘルパーは条件付きの句を構築します。Fragments.whereAndOptはオプションのフィルターを結合し、指定されているものだけを出力します。
これは安全な動的検索クエリを構築するための慣用的な方法です。
import doobie.util.fragments._
val emailOpt: Option[String] = Some("a@b.com")
val filter = whereAndOpt(emailOpt.map(e => fr"email = $e"))
val q = (fr"select id, email, active from accounts" ++ filter)ビルド時のクエリ検証
Doobieのcheck解析はデータベーススキーマに対してクエリを実行し、列の型と数がScalaの型と一致することを検証します。
テストで使用すると、本番環境に到達する前にスキーマのずれを検出できます。
import doobie.scalatest._
// inside a spec mixing in IOChecker
check(sql"select id, email, active from accounts".query[Account])クイックチェック
適切なアキュムレーターを選んでください。
まとめ
sql補間子はパラメーター化されたFragmentを構築し、.query[A]はそれをRead[A]でマッピングされたQuery0[A]に変換します。
行の収集には.unique、.option、.to[List]、.streamのいずれかを選びます。動的な句にはFragmentsを使い、スキーマに対する検証にはcheckを使います。
よくある質問
「クエリを実行する」レッスンは無料ですか?
はい。「クエリを実行する」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Scala for Backend Engineering & Functional Programmingコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Scala for Backend Engineering & Functional Programmingコースには全4レッスンが含まれています。
「クエリを実行する」で何を学びますか?
行をケースクラスに読み込みます。 ブラウザで直接実行するハンズオンコードでScala for Backend Engineering & Functional Programmingを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Scala for Backend Engineering & Functional Programmingを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのScala for Backend Engineering & Functional Programmingは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。
「クエリを実行する」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このScala for Backend Engineering & Functional Programmingレッスンでコードを書いて実行できますか?
はい。すべてのScala for Backend Engineering & Functional Programmingレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。