0Pricing
Scala for Backend Engineering & Functional Programming · บทเรียน

เรียกใช้คำสั่งค้นหา

อ่านแถวข้อมูลเป็นคลาสแบบเคส

เรียกใช้คำสั่งค้นหา เป็นบทเรียน Scala for Backend Engineering & Functional Programming ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Scala for Backend Engineering & Functional Programming และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Scala for Backend Engineering & Functional Programming มีบทเรียนทั้งหมด 4 บทเรียน

ตัวแทรกสตริง sql

ตัวแทรกสตริง sql ของ Doobie เป็นแกนหลักของการสอบถาม โดยจะแยกวิเคราะห์ 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 ใช้ typeclass 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 ต้องการแถวพอดีหนึ่งแถว .option ต้องการศูนย์หรือหนึ่งแถว และ .to[List] จะรวบรวมทุกแถว

แต่ละแบบคืนค่าเป็น ConnectionIO ซึ่งคุณจะเรียก .transact ในภายหลัง

val one: ConnectionIO[User] = q.unique
val maybe: ConnectionIO[Option[User]] = q.option
val all: ConnectionIO[List[User]] = q.to[List]

การแมปแถวกับคลาสกรณี

Doobie สร้างอินสแตนซ์ Read สำหรับคลาสกรณีโดยอัตโนมัติ เมื่อแต่ละฟิลด์มีการแมปคอลัมน์ ลำดับคอลัมน์ต้องตรงกับรายการ 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 ทำให้เคอร์เซอร์ดึงข้อมูลครั้งละ 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]

การสร้าง SQL ด้วย Fragments

ค่า 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 แบบไดนามิก

ตัวช่วย Fragments ของ Doobie ใช้สร้างอนุประโยคแบบมีเงื่อนไข Fragments.whereAndOpt จะรวมตัวกรองที่เป็นทางเลือก และสร้างเฉพาะตัวกรองที่มีค่า

นี่เป็นวิธีตามรูปแบบของ Doobie สำหรับสร้างคิวรีค้นหาแบบไดนามิกที่ปลอดภัย

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)

ตรวจสอบคิวรีขณะสร้าง

การวิเคราะห์ด้วย check ของ Doobie จะเรียกใช้คิวรีกับโครงสร้างฐานข้อมูลเพื่อตรวจสอบว่าชนิดและจำนวนคอลัมน์ตรงกับชนิดของ Scala หรือไม่

เมื่อนำไปใช้ในชุดทดสอบ จะช่วยตรวจพบความคลาดเคลื่อนของโครงสร้างฐานข้อมูลก่อนที่จะไปถึงระบบจริง

import doobie.scalatest._

// inside a spec mixing in IOChecker
check(sql"select id, email, active from accounts".query[Account])

ตรวจสอบอย่างรวดเร็ว

เลือกตัวรวบรวมผลลัพธ์ให้เหมาะสม

สรุปทบทวน

ตัวแทรกสตริง sql จะสร้าง Fragment ที่มีพารามิเตอร์ ส่วน .query[A] จะเปลี่ยนให้เป็น Query0[A] ซึ่งแมปผ่าน Read[A]

เลือกใช้ .unique, .option, .to[List] หรือ .stream เพื่อรวบรวมแถว ใช้ Fragments สำหรับอนุประโยคแบบไดนามิก และใช้ check เพื่อตรวจสอบกับโครงสร้างฐานข้อมูล

คำถามที่พบบ่อย

บทเรียน “เรียกใช้คำสั่งค้นหา” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “เรียกใช้คำสั่งค้นหา” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Scala for Backend Engineering & Functional Programming ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Scala for Backend Engineering & Functional Programming มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “เรียกใช้คำสั่งค้นหา”

อ่านแถวข้อมูลเป็นคลาสแบบเคส คุณปฏิบัติ Scala for Backend Engineering & Functional Programming ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Scala for Backend Engineering & Functional Programming หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Scala for Backend Engineering & Functional Programming บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน

บทเรียน “เรียกใช้คำสั่งค้นหา” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Scala for Backend Engineering & Functional Programming นี้ได้ไหม

ได้ บทเรียน Scala for Backend Engineering & Functional Programming ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. เชื่อมต่อด้วยทรานแซกเตอร์
  2. เรียกใช้คำสั่งค้นหา
  3. การแทรกและอัปเดต
  4. ประกอบธุรกรรม
← กลับไปที่ Scala for Backend Engineering & Functional Programming