3

在遷移到Play 2.5時,我採用了依賴注入設計模式,包括用於(JDBC)數據庫訪問。使用case class/companion對象模式時的Scala依賴注入

在一流水平,我理解這個概念:

class Users @Inject() (db: Database) 

但我還沒有看到如何,當你需要的情況下階層和同伴對象模式的方法內的數據庫訪問,這可能應用的討論。一個例子基本模型之中:

package models 

import anorm._ 
import anorm.SqlParser._ 
import javax.inject._ 

import play.api.db._ 
import play.api.libs.functional.syntax._ 
import play.api.libs.json._ 


case class User @Inject() (db: Database) (
    id: Option[Long] = None, 
    email: String 
) { 
    def save = { 
     id.map { id => User.findById(id) } match { 
      case None => create 
      case _ => update 
     } 
    } 

    def create = db.withConnection { implicit conn => 
     SQL(
      """INSERT INTO users (email) VALUES ({email})""" 
     ).on(
      'email -> email 
     ).executeUpdate() 

     this 
    } 

    def update = ... 
} 

object User {  
    val simple = { 
     get[Option[Long]]("id") ~ 
     get[String]("email") map { 
      case id ~ email => 
       User(id, email) 
     } 
    } 

    def findById(id: Long) = db.withConnection { implicit conn => 
     SQL("""SELECT * FROM users WHERE id = {id}""").on('id -> id).as(User.simple.singleOpt) 
    } 
} 

這改變的情況下類的簽名(使其無法使用內val simple = { ... }),我無法弄清楚如何注入/在同伴對象訪問數據庫。在對象內嘗試@Inject() var db: Database _會導致我想避免的NullPointerException的世界。

在一個依賴注入的世界中,這種常見用例的推薦設計模式是什麼?

+4

案例類並不意味着封裝這樣的「服務」功能,而DI也不是用於與對象一起工作 – cchantep

回答

6

一種常見的模式是將數據庫功能放入單獨的類中。你的情況只留下數據與用戶:

case class User(id: Option[Long] = None, email: String) 

並把數據庫功能集成到一個單獨的類:

class UserRepository @Inject()(db: Database) { 
    def save(user: User) = { ... } 
    def create() : User = { ... } 
    def findById(id: Long) : Option[User] = { ... } 
} 

不知道怎麼你會在使用的User對象的碼。但是對於這種模式,您不會在每個用戶對象基本上將持久性實現泄漏到使用用戶對象的任何地方的情況下對數據庫進行引用。也許你想要這樣做,但是如何在val simple = ...中創建User對象表明我想要創建包含數據的用戶對象。

現在您正在傳遞用戶對象,並且只有在需要數據庫功能時纔會注入UserRepository

這不完全提供了有關依賴注入到伴隨對象的問題的答案,但無論如何可能有幫助。

+0

謝謝!這是一個很好的模式 - 我應該也提到我正在從「Learning Play!Framework 2」書籍的以前的Play <2.5實現中工作:https://github.com/andypetrella/play2-book-chapters/blob/ master/chap4/play-sbook/app/models/User.scala –

+0

我打算繼續並將其標記爲已接受的答案,因爲我認爲這是對預期問題最接近的重構。看起來上面這本書提出的模式並不是最實用的模式。 –