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

數(shù)據(jù)庫連接和事務(wù)處理

你可以在程序的任何地方使用數(shù)據(jù)庫查詢,當(dāng)執(zhí)行查詢時(shí)你需要有一個(gè)數(shù)據(jù)庫連接。

你可以通過創(chuàng)建一個(gè) Database 對(duì)象來連接一個(gè) JDBC 數(shù)據(jù)庫,有多種方法可以創(chuàng)建一個(gè)數(shù)據(jù)庫對(duì)象。

使用 JDBC URL

你可以使用 JDBC URL 來創(chuàng)建一個(gè) Database 對(duì)象(URL 的格式取決于連接的數(shù)據(jù)庫的類型), 比如:

val db = Database.forURL("jdbc:h2:mem:test1;DB_CLOSE_DELAY=-1", driver="org.h2.Driver")

創(chuàng)建一個(gè)基于內(nèi)存的 H2 數(shù)據(jù)庫連接,再比如我們之前使用的 MySQL 數(shù)據(jù)庫,可以使用

val db = Database.forURL("jdbc:mysql://127.0.0.1/Chinook",
    driver = "com.mysql.jdbc.Driver",
    user="user",
    password="password")

使用 DataSource

你可以使用已有的 datasource 對(duì)象,來構(gòu)建一個(gè) Database 對(duì)象,比如你從連接池中取得一個(gè) Datasource 對(duì)象,然后連接到 Slick 庫中

val db = Database.forDataSource(dataSource: javax.sql.DataSource)

之后你創(chuàng)建一個(gè) Session 對(duì)象,將從連接池中取得一個(gè)數(shù)據(jù)庫連接,當(dāng)關(guān)閉 Session 時(shí),連接退回給連接池以作他用。

使用 JNDI 名稱

如果你使用 JNDI,你可以提供 JNDI 名稱來構(gòu)建一個(gè) Database 對(duì)象:

val db = Database.forName(jndiName: String)

Session 管理

現(xiàn)在你有了一個(gè)數(shù)據(jù)庫對(duì)象可以打開一個(gè)數(shù)據(jù)庫(Slick 函數(shù)庫封裝了一個(gè) Session 對(duì)象)

Database 的 withSession 方法,創(chuàng)建一個(gè) Session 對(duì)象,它可以傳遞給一個(gè)函數(shù),函數(shù)返回時(shí)自動(dòng)關(guān)閉這個(gè) Session 對(duì)象,如果你使用連接池,關(guān)閉 Session 對(duì)象,自動(dòng)將連接退回連接池。

val query = for (c <- coffees) yield c.name
val result = db.withSession {
    session =>
    query.list()( session )
}

你可以看到,我們可以在 withSession 之外定義查詢,只有在實(shí)際執(zhí)行查詢時(shí)才需要一個(gè) Session 對(duì)象,要注意的是 Session 的缺省模式為自動(dòng)提交(auto-commit )模式。每個(gè)數(shù)據(jù)庫指令(比如 insert )都自動(dòng)提交給數(shù)據(jù)庫。 如果需要將幾個(gè)指令作為一個(gè)整體,那么就需要使用事務(wù)處理(Transaction) 上面的例子,我們?cè)趫?zhí)行查詢時(shí),明確指明了 session 對(duì)象,你可以使用隱含對(duì)象來避免這種情況,比如:

val query = for (c <- coffees) yield c.name
val result = db.withSession {
    implicit session =>
    query.list // <- takes session implicitly
}
// query.list // <- would not compile, no implicit value of type Session

手工管理 Session

這不是推薦使用的情況,但如果你需要自己管理 Session 對(duì)象,你可以自己管理 Session 的生命周期:

val query = for (c <- coffees) yield c.name
val session : Session = db.createSession
val result  = query.list()( session )
session.close

事務(wù)處理

你可以使用 Session 對(duì)象的 withTransaction 方法來創(chuàng)建一個(gè)事務(wù),傳給該方法的語句將作為一個(gè)整體事務(wù)執(zhí)行,如果出現(xiàn)異常,Slick 自動(dòng)回滾事務(wù),你也可以使用 rollback 強(qiáng)制事務(wù)回滾,要注意的是 Slick 只會(huì)回滾數(shù)據(jù)庫相關(guān)操作,而不會(huì)取消其它 Scala 語句。

session.withTransaction {
    // your queries go here

    if (/* some failure */ false){
        session.rollback // signals Slick to rollback later
    }

} //

如果你沒有 Session 對(duì)象,也可以直接使用數(shù)據(jù)庫對(duì)象的 withTransaction 方法,如:

db.withTransaction{
    implicit session =>
    // your queries go here
}
上一篇:基本查詢下一篇:查詢(二)