我們之前 Slick 編程(2): 準(zhǔn)備開發(fā)環(huán)境使用自動(dòng)代碼生成工具生成數(shù)據(jù)庫表的 Slick 定義(使用 Lifted Embedding API ),本篇介紹如何手工來寫這些 Schema 定義。
數(shù)據(jù)庫表 Tables
為了能夠使用 Slick 的 Lifted Embedding API 定義類型安全的查詢,首先我們需要定義數(shù)據(jù)庫表代表表中每行數(shù)據(jù)的類和對(duì)應(yīng)于數(shù)據(jù)庫表的 Schema 的 TableQuery 值,我們先看看自動(dòng)生成的 Album 表個(gè)相關(guān)定義:
/** Entity class storing rows of table Album
* @param albumid Database column AlbumId PrimaryKey
* @param title Database column Title
* @param artistid Database column ArtistId */
case class AlbumRow(albumid: Int, title: String, artistid: Int)
/** GetResult implicit for fetching AlbumRow objects using plain SQL queries */
implicit def GetResultAlbumRow(implicit e0: GR[Int], e1: GR[String]): GR[AlbumRow] = GR{
prs => import prs._
AlbumRow.tupled((<<[Int], <<[String], <<[Int]))
}
/** Table description of table Album. Objects of this class serve as prototypes for rows in queries. */
class Album(tag: Tag) extends Table[AlbumRow](tag, "Album") {
def * = (albumid, title, artistid) <> (AlbumRow.tupled, AlbumRow.unapply)
/** Maps whole row to an option. Useful for outer joins. */
def ? = (albumid.?, title.?, artistid.?).shaped.<>(
{r=>import r._; _1.map(_=> AlbumRow.tupled((_1.get, _2.get, _3.get)))},
(_:Any) => throw new Exception("Inserting into ? projection not supported."))
/** Database column AlbumId PrimaryKey */
val albumid: Column[Int] = column[Int]("AlbumId", O.PrimaryKey)
/** Database column Title */
val title: Column[String] = column[String]("Title")
/** Database column ArtistId */
val artistid: Column[Int] = column[Int]("ArtistId")
/** Foreign key referencing Artist (database name FK_AlbumArtistId) */
lazy val artistFk = foreignKey("FK_AlbumArtistId", artistid, Artist)
(r => r.artistid, onUpdate=ForeignKeyAction.NoAction, onDelete=ForeignKeyAction.NoAction)
}
/** Collection-like TableQuery object for table Album */
lazy val Album = new TableQuery(tag => new Album(tag))
所有的字段(Column)使用 column 方法來定義,每個(gè)字段對(duì)應(yīng)一個(gè) Scala 類型和一個(gè)字段名稱(對(duì)應(yīng)到數(shù)據(jù)庫表的定義),下面為 Slick 支持的基本數(shù)據(jù)類型:
支持 Null 的字段使用 Option[T] 來表示,其中 T 為上述基本數(shù)據(jù)類型,在字段名稱之后,你可以使用一些可選的字段定義,這些可選定義定義在 table 的 O 對(duì)象中。下面為常用的定義
PrimaryKey 表明該字段為主鍵Default[T](defaultValue: T) 該字段缺省值DBType(dbType: String) 非標(biāo)準(zhǔn)字段類型,比如 DBType(“VARCHAR(20)”) 做為 String 類型AutoInc 自動(dòng)增一的字段NotNull,Nullable 表明該字段是否可以為空
每個(gè)表定義都需要一個(gè)""方法定義了缺省映射,這定義了執(zhí)行查詢返回表格一行時(shí)的數(shù)據(jù)類型,Slick 的””不要求和數(shù)據(jù)庫表的定義一一映射,你可以添加字段(復(fù)合字段)或者省略掉某個(gè)字段。
匹配過的表定義
可以使用自定義的數(shù)據(jù)類型做為”*”的映射,這可以使用雙向映射操作符”“來完成。
比如:
def * = (albumid, title, artistid) <> (AlbumRow.tupled, AlbumRow.unapply)
約束
外鍵約束可以使用foreignKey來定義
/** Foreign key referencing Artist (database name FK_AlbumArtistId) */
lazy val artistFk = foreignKey("FK_AlbumArtistId", artistid, Artist)
(r => r.artistid, onUpdate=ForeignKeyAction.NoAction, onDelete=ForeignKeyAction.NoAction)
它的參數(shù)為外鍵約束的名稱,本表字段名稱,外鍵所在表名稱,和一個(gè)函數(shù),這個(gè)函數(shù)定義了外鍵約束,以及更新和刪除外鍵時(shí)的行為)
主鍵約束可以使用 primaryKey 來定義,這主要用作定義復(fù)合主鍵的情況
/** Primary key of Playlisttrack (database name PlaylistTrack_PK) */
val pk = primaryKey("PlaylistTrack_PK", (playlistid, trackid))
其它比如索引的情況和主鍵約束非常類似,比如:
class A(tag: Tag) extends Table[(Int, Int)](tag, "a") {
def k1 = column[Int]("k1")
def k2 = column[Int]("k2")
def * = (k1, k2)
def idx = index("idx_a", (k1, k2), unique = true)
// compiles to SQL:
// create unique index "idx_a" on "a" ("k1","k2")
}
數(shù)據(jù)庫定義語言 DDL
數(shù)據(jù)庫定義語句可以使用 TableQuery 的 ddl 方法,多個(gè) DDL 對(duì)象可以使用 ++ 連接,比如:
val ddl = coffees.ddl ++ suppliers.ddl
db withDynSession {
ddl.create
//...
ddl.drop
}
ddl.create 和 ddl.drop 可以創(chuàng)建表和刪除表,如果需要看看對(duì)應(yīng)的 SQL 語句,可以使用
val ddl = Album.ddl
ddl.createStatements.foreach(println)
ddl.dropStatements.foreach(println)
對(duì)應(yīng)的 MySQL 語句為
create table `Album` (`AlbumId` INTEGER NOT NULL PRIMARY KEY,`Title` VARCHAR(254) NOT NULL,`ArtistId` INTEGER NOT NULL)
alter table `Album` add constraint `FK_AlbumArtistId` foreign key(`ArtistId`) references `Artist`(`ArtistId`) on update NO ACTION on delete NO ACTION
ALTER TABLE Album DROP FOREIGN KEY FK_AlbumArtistId
drop table `Album`
更多建議: