scala – Slick 3:如何使用事务实现存储库模式?
在我的play framework(2.5)app中,我需要为服务编写单元测试.
我需要隔离数据访问逻辑,以便能够单独测试服务层, class UserService { def signUpNewUser(username: String,memberName: String): Future[Unit] { val userId = 1 // Set to 1 for demo val user = User(userId,username) val member = Member(memberName,userId) // ---- I NEED TO EXECUTE THIS BLOCK WITHIN TRANSACTION ---- for { userResult <- userRepository.save(user) memberRepository.save(member) } yield () // ---- END OF TRANSACTION ---- } } 在上面的示例中,userRepository.save(User)和memberRepository.save(member)操作应该在事务中执行. 我不想直接在我的服务层使用光滑,因为它会使我的测试复杂化. 另外,我不想在我的单元测试中使用嵌入式数据库,在其他地方它将是一个NOT单元测试,我需要完全隔离. 我不希望我的存储库接口完全依赖于光滑,但是需要这样的东西: trait UserRepository { findById(id: Long): Future[Option[User]] save(user: User): Future[Unit] } 如何用光滑实现这一目标? 解决方法
好的 – 让我们将您的问题分解为三个部分.
如何在事务中执行块 基本上读了这个答案:How to use transaction in slick 一旦你将DBIO转换为Future,你就完成了.没有机会在单个交易中组成多个操作.故事结局. 如何避免在测试中使用Slick 这基本上是一个设计问题 – 如果你想在Repository / DAO /之上有一个业务层 – 而不是让这个服务层处理事务.您不需要在此图层之外与Slick交互. 避免存储库接口依赖于Slick 以最简单的方式 – 您需要依赖Slick DBIO来组成事务中的操作(并且在事务中组合Repository方法是在任何严肃的应用程序中都无法避免的). 如果你想避免依赖DBIO,你可能会创建自己的monadic类型,比如TransactionBoundary [T]或TransactionContext [T]. 那么你会有类似TransactionManager的东西来执行这个TransactionContext [T]. 恕我直言不值得努力,我只是使用DBIO,它已经有一个很棒的名字(比如Haskell的IO monad – DBIO告诉你你有关于你的存储上执行的IO操作的描述).但我们假设你仍然想避免它. 你可以这样做: package transaction { object Transactions { implicit class TransactionBoundary[T](private[transaction] val dbio: DBIO[T]) { // ... } } class TransactionManager { def execute[T](boundary: TransactionBoundary[T]): Future[T] = db.run(boundary.dbio) } } 你的特质看起来像这样: trait UserRepository { findById(id: Long): TransactionBoundary[Option[User]] save(user: User): TransactionBoundary[Unit] } 在你的代码中的某个地方,你会这样做: transactionManager.execute( for { userResult <- userRepository.save(user) memberRepository.save(member) } yield () ) 通过使用隐式转换,您可以将Repository中的方法结果自动转换为TransactionBoundary. 但是再次 – 恕我直言,上述所有这些都没有带来任何比使用DBIO更有实际优势(除了美学的味道).如果您想避免在某个图层之外使用Slick相关类,只需创建一个类型别名: type TransactionBoundary[T] = DBIO[T] 并在任何地方使用它. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |