【问题标题】:Injecting database methods from the service layer to the storage layer将数据库方法从服务层注入到存储层
【发布时间】:2014-03-31 03:53:18
【问题描述】:

我们的应用在存储层之上有一个服务层——服务层方法将创建一个新的数据库会话(我们在 MySql 之上使用Slick)并将会话作为隐式参数传递给存储分层方法

trait Service1 {
  def serviceLayerMethod(params) = {
    db withSession {
      implicit session: Session =>
        storageLayerMethod1(params)
        storageLayerMethod2(params)
}}}

object DAO1 {
  def storageLayerMethod1(params)(implicit session: Session)
}

object DAO2 {
 def storageLayerMethod2(params)(implicit session: Session)
}

我们希望能够从服务层向存储层注入不同的方法实现,例如我们有一个检索多条记录的multiGet 方法,我们希望这个方法有不同的实现例如一个并行执行multiGet,另一个尝试在从数据库中提取数据之前从 Redis 缓存中检索数据。我可以将这些方法作为隐式参数传递,但我希望有一种方法可以用更少的样板来做到这一点。

trait MultiGet {
  def multiGet(params)(implicit session: Session)
}

object MultiGetDefault extends MultiGet
object MultiGetParallel extends MultiGet
object MultiGetCached extends Multiget

trait Servic1 {
  def serviceLayerMethod1(params) = {
    db withSession {
      implicit session: Session =>
        storageLayerMethod1(params)(MultiGetDefault)
  }}

  def serviceLayerMethod2(params) = {
    db withSession {
      implicit session: Session =>
        storageLayerMethod1(params)(MultiGetParallel)
}}}

object DAO1 {
  def storageLayerMethod1(params)(implicit session: Session, multiGetImpl: MultiGet) {
    multiGetImpl.multiGet(params)
}}

大多数存储层方法都在单例对象中,因此我无法在不进行重大重构的情况下混合不同的MultiGet 实现。服务层特征正在通过蛋糕模式在控制器层实例化/注入。

【问题讨论】:

标签: scala dependency-injection slick


【解决方案1】:

我们将尝试使用实现multiGet 等的版本来扩展/包装Session

trait MySession extends Session {
  private val session: Session

  def capabilities = session.capabiliites
  def close = session.close
  def conn = session.conn
  ...

  def multiGet(tableName: String, ids: Seq[Int])
}

class DefaultSession(private val session: Session) extends MySession {
  def multiGet(tableName: String, ids: Seq[Int]) // default implementation
}

class ConcurrentSession(private val session: Session) extends MySession {
  def multiGet(tableName: String, ids: Seq[Int]) // concurrent implementation
}

def defaultExecute[T](fun: (MySession) => T): T = db withSession {
  _session: Session =>
    fun(new DefaultSession(_session))
}

def concurrentExecute[T](fun: (MySession) => T): T = db withSession {
  _session: Session =>
    fun(new ConcurrentSession(_session))
}

【讨论】:

    猜你喜欢
    • 2015-01-03
    • 1970-01-01
    • 1970-01-01
    • 2012-07-25
    • 1970-01-01
    • 2021-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多