所有参与服务交易的Slick Repo方法

时间:2015-06-22 18:35:56

标签: scala slick-2.0

我目前有一组以约定*SlickRepo命名的数据访问对象。例如,UserSlickRepoDistributionSlickRepoContentSlickRepo等......

这些Repos中的每一个都有基本符合此约定的方法:

trait SomethingRepoImpl extends SomethingRepo {
  val somethingRepo: SomethingRepo = new SomethingRepoImpl

  class SomethingRepoImpl extends SomethingRepo with MySlickDatastore {

    def getSomething(id: UUID): Either[SomethingNotFoundError, Something] = {
      getDatabase withDynSession {
        // Slick stuff
      }
    }
    def createSomething .....
  }
}

现在处于服务级别,我们在这个repo类中进行烘焙,我们的方法看起来像这样:

trait SomethingServiceImpl extends SomethingService {

  dep: SomethingRepo with SomethingElseRepo =>


  val somethingService = new SomethingServiceImpl

  class SomethingServiceImpl extends SomethingService {

    def createSomethingGood(): Either[SomeError, (Something, SomethingElse)] = {
      (dep.somethingRepo.createSomething, dep.somethingElseRepo.createSomethingElse)
    }

  }
}

我们现在希望createSomethingGood实际运行事务中的两个repo方法。由于所有Slick内容都被锁定在Slick特定的Repo方法中,这样做的最佳方法是什么?我并不反对在我的*ServiceImpl类中使用特定于Slick的代码(我的意思很奇怪,但确定),但是这意味着我必须更改我的Repo类以删除getDatabase withDynSession类型代码一起,而是从服务层传递一个会话?对我而言,这似乎是错误的。

2 个答案:

答案 0 :(得分:4)

从我的观点来看,正确的方法是将createSomethingcreateSomethingElse添加到一个*RepoSomethingRepoSomethingElseRepo)交易方法({{ 1}})。这不是一个漂亮的解决方案,但对我来说尽可能简单,因为这些实体是逻辑连接的(我们可以从这段代码withTransaction {...}看到))我认为在一个DAO类中混合操作2个实体并不是一个大的违规行为。如果我错了,请修理我。

答案 1 :(得分:0)

也许有另一种方式。我自己没有尝试过,但想法是你可以有一个实际传递给Repo的Session包装器。

必须在服务层创建包装器,但是您可以在配对对象上抽象特定的实现,这样服务层实际上不会处理Slick,而是像

SessionWrapper.transactional: Session

我希望这会有所帮助,如果我自己试一试,我会在回复中添加更多内容。