3

Play 2.5への移行では、(JDBC)データベースアクセスを含む依存性注入デザインパターンを採用しています。クラスレベルでケースクラス/コンパニオンオブジェクトパターンを使用する場合の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 = { ... }内それが使用できなくなる)の署名を変更し、そしてIは、コンパニオン・オブジェクトでDBにアクセス/注入する方法を見つけ出すことができません。オブジェクト内で@Inject() var db: Database _を試してみると、避けたいNullPointerExceptionsの世界ができます。

依存性注入の世界でこの一般的な使用例に推奨されるデザインパターンは何ですか?

+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オブジェクトを使用することがあります方法を知ってはいけませんコード。しかし、このパターンでは、基本的にすべてのユーザーオブジェクトでデータベースへの参照を渡すことはありません。たぶんあなたはこれを持っているが、Userオブジェクトをどのように作成するかは、val simple = ...には、データだけのユーザーオブジェクトを作成したいということがわかります。

ここでは、データベース機能が必要な場合にのみ、ユーザオブジェクトを渡しています。UserRepositoryを注入してください。

これは、コンパニオンオブジェクトへの依存性注入に関する質問への回答を正確には提供しませんが、とにかく助けになるかもしれません。

+0

ありがとう!これは良いパターンです - 私は、 "Play Play!Framework 2"の本のPlay <2.5の実装に反対しています:https://github.com/andypetrella/play2-book-chapters/blob/ –

+0

私は先に進んでこれを受け入れられた答えとしてマークします。これは、意図した質問に最も近いリファクタリングだと思います。上記の本に示されているパターンは、最も機能的ではないようです。 –

関連する問題