鍍金池/ 教程/ Scala/ 查詢(三)
概述
基本查詢
查詢(二)
查詢(三)
直接使用 SQL 語句
數(shù)據(jù)庫連接和事務(wù)處理
數(shù)據(jù)庫 Schema
查詢(一)
準(zhǔn)備開發(fā)環(huán)境

查詢(三)

Slick 的查詢實(shí)際上是執(zhí)行由 Invoker(無參數(shù)時(shí)為 UnitInvoker ) Trait 定義的方法,Slick 定義了一個(gè)從 Query 隱含的變換,使得你可以直接執(zhí)行查詢操作,最常用的一個(gè)情況是把整個(gè)查詢結(jié)果存放到一個(gè) Scala 集合類型中(比如使用 list 方法)

val l = q.list
val v = q.buildColl[Vector]
val invoker = q.invoker
val statement = q.selectStatement

所有的查詢方法都定義了一個(gè)隱含參數(shù) Session,如果你愿意,你也可以直接傳入一個(gè) session 參數(shù):

val l = q.list()(session)

如果你只需要單個(gè)查詢結(jié)果,你可以使用 first 或 firstOption 方法,而方法 foreach, foldLeft 和 elements 方法可以用來遍歷查詢結(jié)果而不需要先把結(jié)果復(fù)制到另外一個(gè) Scala 集合對象中。

Deleting

刪除數(shù)據(jù)和查詢很類似,你首先寫一個(gè)選擇查詢,然后調(diào)用它的 delete 方法,同樣 Slick 也定義一個(gè)從 Query 到 DeleteInvoker 的隱含轉(zhuǎn)換,DeleteInvoker 定義了 delete 方法

val affectedRowsCount = q.delete
val invoker = q.deleteInvoker
val statement = q.deleteStatement

定義用來刪除記錄的查詢時(shí)只能使用單個(gè)表格。

Inserting

插入操作基于單個(gè)表定義的字段映射,當(dāng)你直接使用某個(gè)表來插入數(shù)據(jù)時(shí),這個(gè)操作基于表類型中定義的“*”,如果你省略某些字段,那么插入這些省略的字段會(huì)使用缺省值,所有的插入操作方法定義在 InsertInvoker 和 FullInsertInvoker。

coffees += ("Colombian", 101, 7.99, 0, 0)

coffees ++= Seq(
  ("French_Roast", 49, 8.99, 0, 0),
  ("Espresso",    150, 9.99, 0, 0)
)

// "sales" and "total" will use the default value 0:
coffees.map(c => (c.name, c.supID, c.price)) += ("Colombian_Decaf", 101, 8.99)

val statement = coffees.insertStatement
val invoker = coffees.insertInvoker

// compiles to SQL:
// INSERT INTO "COFFEES" ("COF_NAME","SUP_ID","PRICE","SALES","TOTAL") VALUES (?,?,?,?,?)

如果你的插入操作定義了自動(dòng)增一的字段,該字段會(huì)自動(dòng)忽略,由數(shù)據(jù)庫本身來插入該字段的值。缺省情況 += 返回受影響的行數(shù)(通??倿?1),而 ++ 操作給出總計(jì)的行數(shù)(以 Option 類型給出),你可以使用 returning 修改返回的值,比如返回插入的行的主鍵:

val userId =
  (users returning users.map(_.id)) += User(None, "Stefan", "Zeiger")

要注意的是很多數(shù)據(jù)庫只支持返回自動(dòng)增一的作為主鍵的那個(gè)字段,如果想返回其它字段,可能會(huì)拋出 SlickException 異常。

除了上面的插入記錄的方法,還可以使用服務(wù)器端表達(dá)式的方發(fā)插入數(shù)據(jù):

class Users2(tag: Tag) extends Table[(Int, String)](tag, "users2") {
    def id = column[Int]("id", O.PrimaryKey)
    def name = column[String]("name")
    def * = (id, name)
}
val users2 = TableQuery[Users2]

users2.ddl.create

users2 insert (users.map { u => (u.id, u.first ++ " " ++ u.last) })

users2 insertExpr (users.length + 1, "admin")

Updating

更新記錄也是先寫查詢,然后調(diào)用 update 方法,比如:

val q = for { c <- coffees if c.name === "Espresso" } yield c.price
q.update(10.49)

val statement = q.updateStatement
val invoker = q.updateInvoker

update 方法定義在 UpdateInvoker Trait 中。

Compiled Queries

數(shù)據(jù)庫查詢時(shí),通常需要定義一些查詢參數(shù),比如根據(jù) ID 查找對應(yīng)的記錄。你可以定義一個(gè)帶參數(shù)的函數(shù)來定義查詢對象,但每次調(diào)用該函數(shù)時(shí)都要重新編譯這個(gè)查詢語句,系統(tǒng)消耗有些大,Slick 支持預(yù)編譯這個(gè)帶參數(shù)的查詢函數(shù),例如:

def userNameByIDRange(min: Column[Int], max: Column[Int]) =
  for {
    u <- users if u.id >= min && u.id < max
  } yield u.first

val userNameByIDRangeCompiled = Compiled(userNameByIDRange _)

// The query will be compiled only once:
val names1 = userNameByIDRangeCompiled(2, 5).run
val names2 = userNameByIDRangeCompiled(1, 3).run

這種方法支持查詢,更新和刪除數(shù)據(jù)。

上一篇:查詢(二)下一篇:概述