如何使用Slick 3.1和DDD实现多DB模式



我正在阅读Debasish Ghosh的功能和反应域建模,我想重构它实际上正在生产中的CRUD应用程序。我专注于使用DI,存储库模式的Reader Monad和ADT的第一种方法,用于管理应用程序之间的等价值(想想一个值,通过某种应用程序以某种方式理解,然后查询其对另一个系统的等价价值)。

debasish指的是存储库模式作为解耦的一种方式,因此,在我的情况下,我需要Oracle和Postgresql和H2的具体实现进行测试。我有以下且非常简单的实现(基于这本书):

基础trait用于存储库:

trait Repository[A, Id] {
  def query(id: Id): Try[Option[A]]
  def insert(a: A): Try[A]
  def update(a: A): Try[A]
  def delete(a: A): Try[A]
}

等价存储库的模块:

trait EquivalenceRepository extends Repository[Equivalence, Long]{
  def query(id: Long): Try[Option[Equivalence]]
  def insert(a: Equivalence): Try[Equivalence]
  def update(a: Equivalence): Try[Equivalence]
  def delete(a: Equivalence): Try[Equivalence]
}

中间混凝土 slick:

class EquivalenceOracleRepository extends EquivalenceRepository {
  def query(id: Long): Try[Option[Equivalence]] = {
    ???
  }
  def insert(a: Equivalence): Try[Equivalence] = {
    ???
  }
  def update(a: Equivalence): Try[Equivalence] = {
    ???
  }
  def delete(a: Equivalence): Try[Equivalence] = {
    ???
  }
}
private[repository] trait EquivalenceOracleDB{
  this: DBComponent =>
  import jdbcProfile.api._
  final case class EquivalenceDTO(
                                    originId: Int,
                                    equivalenceId: Int,
                                    creator: String,
                                    creationDate: Timestamp,
                                    isActive: Boolean
                                  )
  final class EquivalenceTable(tag: Tag) extends Table[Equivalence](tag, "Equivalence"){
    def originId: Rep[Int] = column[Int]("ORIGIN_ID", O.SqlType("NUMBER(10)"))
    def equivalenceId: Rep[Int] = column[Int]("EQUIVALENCE_ID", O.SqlType("NUMBER(10)"))
    def creator: Rep[String] = column[String]("CREATOR", O.SqlType("NUMBER(10)"))
    def creationDate: Rep[Timestamp] = column[Timestamp]("CREATION_DATE", O.SqlType("TIMESTAMP(6)"))
    def isActive: Rep[Boolean] = column[Boolean]("IS_ACTIVE", O.SqlType("VARCHAR2(1)"))
    def pk: PrimaryKey = primaryKey("EQUIVALENCES_PK", (originId, equivalenceId))
    def * : ProvenShape[EquivalenceDTO] =
      (originId, equivalenceId, creator, creationDate, isActive) <> (EquivalenceDTO.tupled, EquivalenceDTO.unapply)
  }
  val table = TableQuery[EquivalenceTable]
}

是甲骨文的最后一个混凝土实现,您可以看到该性状正在期望DBComponent。这是一个特征,其代码是从实际生产应用程序继承的,并试图为每个DBMS定义混凝土光滑配置文件:

这是每个DBMS的分析:

trait Profile {
  val jdbcProfile: JdbcProfile
}
object OracleProfile extends Profile {
  override val jdbcProfile: JdbcProfile = OracleDriver
}
object H2Profile extends Profile {
  override val jdbcProfile: JdbcProfile = H2Driver
}
object PostgreSQLProfile extends Profile {
  override val jdbcProfile: JdbcProfile = PostgreSQLProfile.jdbcProfile
}

这是数据库定义:

trait DBComponent {
  val jdbcProfile: JdbcProfile
  import jdbcProfile.api._
  val db: Database
}
trait OracleDB extends DBComponent {
  val logger: Logger = LoggerFactory.getLogger(this.getClass)
  val jdbcProfile: JdbcProfile = OracleProfile.jdbcProfile
}
trait H2DB extends DBComponent {
  val logger: Logger = LoggerFactory.getLogger(this.getClass)
  val jdbcProfile: JdbcProfile = H2Profile.jdbcProfile
}
trait PostgreSQLDB extends DBComponent {
  val logger: Logger = LoggerFactory.getLogger(this.getClass)
  val jdbcProfile: JdbcProfile = PostgreSQLProfile.jdbcProfile
}

但是我的疑问是在这里:如果我尝试将包含光滑基础知识的EquivalenceOracleDB特征混合到EquivalenceOracleRepository中,我也需要混合组件,实际上我会遇到错误:

MIXIN:

class EquivalenceOracleRepository extends EquivalenceRepository with EquivalenceOracleDB{

和错误:Illegal inheritance, self-type EquivalenceOracleRepository does not conform to DBComponent,因为接口的不匹配。所以,我需要一些光:

  • 是否有一个已知的具体滑动多DB实现,我可以与Debasish?
  • 如何改善我的具体实现的设计,以符合书中定义的存储库模式,并且截至目前还没有弄乱具体和抽象的实现?(保持关注点分开)

我已经看到了LightBend具有的多DB示例,但是,除了未解决的依赖问题之外,它严重依赖蛋糕模式,这是非常详细的。我正在尝试坚持这本书。

任何帮助将不胜感激。

谢谢

您遇到这样的错误的原因是您没有混合OracleDB。您应该替换:

class EquivalenceOracleRepository extends EquivalenceRepository with EquivalenceOracleDB

class EquivalenceOracleRepository extends EquivalenceRepository with EquivalenceOracleDB with OracleDB

现在您会遇到一个错误,即db未定义,因此您应该在某个地方提供其实现(因为它在DBComponent中定义为摘要)。我认为这可以在OracleDB中完成,这将使该性状具体而不是现在的特征。我认为这种方式将或多或少地符合书中介绍的设计(您具有描述存储库的抽象接口,以及多个具体/生产实现)。

最新更新