【发布时间】:2018-03-21 11:32:46
【问题描述】:
我有一个关于持久层抽象的问题。
目标
创建一个与 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
}
在服务中,我使用 implicit conversion 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)
}
问题
所有这些抽象都需要实现,问题就从这里开始。
我认为我必须放弃 repositories 抽象,因为不经意间要使用 slick BDIO 方法,我需要对其进行具体访问,这会将我的代码与 Slick 联系起来,但我认为没关系。
实体与我的 trait(Entity) 无关,但麻烦在于与 repos 的集成。
我的 slick repos 从 Slick-repo 插件扩展了 Repository 类,这些类(就像我的 IRepository trait)需要两个泛型类型,第一个必须扩展一个 trait命名实体(Slick-repo 的特征),而第二个没有约束并表示实体的 id 类型。
总结:
我的课程
- IRepository[实体,ID]
- 实体[实体,ID]
- SlickRepository[Entity, ID] 扩展了 IRepository
Slick-repo 类
- 存储库[实体,ID]
- 实体[实体,ID]
SlickRepository 扩展/应该使用 Repository(Slick-repo) 但该类希望第一个通用参数扩展 Entity(Slick-repo) 而在我的情况下,为了分离,它扩展了实体特征(我的域特征)
我希望清楚,我知道情况有点复杂,尤其是因为某些类具有相同的名称
也许我对这个问题的概念是完全错误的我不知道我希望有人能帮助我。
感谢大家的建议。
【问题讨论】:
标签: scala playframework architecture slick abstraction