持久层抽象[Slick]

时间:2018-03-21 11:32:46

标签: scala playframework architecture slick abstraction


我有一个关于持久层抽象的问题。

目标

创建一个不具有Slick相关性的结构,因此 Entities 必须与Slick和Slick-repo插件脱节。

现状

环境

  
      
  • Scala%2.12.4
  •   
  • com.typesafe.play%sbt-plugin%2.6.12
  •   
  • com.typesafe.play%play-slick%3.0.3
  •   
  • com.byteslounge%Slick-repo%1.4.3
  •   

目前我已经创建了具有以下特征的抽象:

IRepository:

trait IRepository[E <: Entity[E, ID], ID] {

  type Transaction[T]

  val transactionManager: TransactionManager[Transaction]
  final type EntityType = E

  def findAll()(implicit ec: ExecutionContext): Transaction[Seq[E]]
  def findOne(id : ID)(implicit ec: ExecutionContext): Transaction[Option[E]]
  def lock(entity: E)(implicit ec: ExecutionContext): Transaction[E]
  def save(entity: E)(implicit ec: ExecutionContext): Transaction[E]
  def batchInsert(entities: Seq[E]): Transaction[Option[Int]]
  def update(entity: E)(implicit ec: ExecutionContext): Transaction[E]
  def delete(entity: E)(implicit ec: ExecutionContext): Transaction[E]
  def count(): Transaction[Int]
  def exclusiveLockStatement(sql: String): String
}

事务管理器:

trait TransactionManager[T[_]] {

  final type Transaction[Entity] = T[Entity]

  implicit def executeAll[Entity](op: Seq[T[Entity]]): Future[Seq[Entity]]

  implicit def execute[Entity](op: T[Entity]): Future[Entity]
}

实体:

trait Entity[T <: Entity[T, ID], ID] {

  final type IdType = ID

  val id: Option[ID]

  def withId(id: ID): T
}

在服务中,我使用隐式转化 scala功能执行 Db操作并获取 Future 实例

这是一个简单的例子:

class UserServiceImpl @Inject()(private val repo: UserRepository)
                               (implicit ec: ExecutionContext) extends UserService {

  import repo.transactionManager._

  override def retrieve(id: Long): Future[Option[User]] =
    repo.findOne(id)

  override def save(user: User): Future[User] =
    repo.save(user)

  override def retrieve(loginInfo: LoginInfo): Future[Option[User]] =
    repo.findByLoginInfo(loginInfo)

  override def delete(user: User): Future[User] =
    repo.delete(user)
}

问题

所有这些抽象都需要实现,这里就会出现问题。

我认为我必须放弃存储库抽象,因为无意中使用光滑的BDIO方法我需要具体访问它,这将我的代码绑定到Slick但我认为它是确定。

实体与我的特质(实体)的光滑无关,但麻烦在于与回购整合。

我的slick repos从 Slick-repo 插件扩展 Repository 类,这些类(比如我的IRepository trait)需要两个泛型类型,第一个必须扩展一个特性名为Entity(Slick-repo&#39; s trait),而第二个没有约束,代表实体的id类型。

总结:

我的班级

  
      
  • IRepository [实体,ID]
  •   
  • 实体[实体,ID]
  •   
  • SlickRepository [实体,ID]扩展了IRepository
  •   

光滑回购课程

  
      
  • 存储库[实体,ID]
  •   
  • 实体[实体,ID]
  •   

SlickRepository扩展/应该使用Repository(Slick-repo),但该类希望第一个泛型参数释放Entity(Slick-repo),而在我的情况下,为了分离,它扩展了Entity trait(我的域特征) )

我希望它清楚,我知道这种情况很复杂,特别是因为有些班级有相同的名字

也许我对这个问题的概念是完全错误的我不知道我希望有人可以帮助我。

感谢所有建议。

1 个答案:

答案 0 :(得分:0)

您可以在此处查看Slick的持久层抽象示例:https://github.com/gonmarques/slick-repo

此存储库提供了一些常见功能,例如:

  • 以类型安全的方式提供常见的数据库操作,例如保存,更新,查找,删除或计数

  • 其他操作,例如事务,批处理插入,乐观锁定(aka版本控制),

  • 还支持悲观锁定或自定义查询/语句执行

  • 为了最大程度地提高性能,所有提供的操作均由Slick文档中的Slick编译查询支持