Play-Slick存储库模式

时间:2018-02-23 18:07:35

标签: scala playframework

我正在尝试使用play-slick插件在PlayFramework应用程序中实现一个简单的存储库。

我是scala的新手,刚接触到新手,新玩家。

在尝试编译我的代码时,我收到以下错误:

type mismatch;
 found   : slick.lifted.TableQuery[UserRepository.this.UserTable]
 required: UserRepository.this.profile.api.TableQuery[UserRepository.this.BaseTable]
    (which expands to)  slick.lifted.TableQuery[UserRepository.this.BaseTable]
Note: UserRepository.this.UserTable <: UserRepository.this.BaseTable, but class TableQuery is invariant in type E.
You may wish to define E as +E instead. (SLS 4.5)

这是我的代码:

trait BaseEntity {
  def id: Long
  def createdAt: LocalDateTime
  def updatedAt: LocalDateTime
  def deletedAt: LocalDateTime
}
case class User (id: Long, firstname: String, lastname: String, password: String, createdAt: LocalDateTime, updatedAt: LocalDateTime, deletedAt: LocalDateTime) extends BaseEntity
abstract class BaseRepository[E <: BaseEntity](protected val dbConfigProvider: DatabaseConfigProvider, executionContext: ExecutionContext) extends HasDatabaseConfigProvider[JdbcProfile] {

  import profile.api._

  implicit val localDateTimeToTimestamp: BaseColumnType[LocalDateTime] = MappedColumnType.base[LocalDateTime, Timestamp](
    l => Timestamp.valueOf(l),
    t => t.toLocalDateTime
  )

  protected abstract class BaseTable(tag: Tag, tableName: String) extends Table[E](tag, tableName) {
    def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
    def createdAt = column[LocalDateTime]("created_at")
    def updatedAt = column[LocalDateTime]("updated_at")
    def deletedAt = column[LocalDateTime]("deleted_at")
  }

  protected val query: TableQuery[BaseTable]

  def all(): Future[Seq[E]] = db.run(query.result)
}
class UserRepository @Inject()(@NamedDatabase("effective-potato-play") override protected val dbConfigProvider: DatabaseConfigProvider)(implicit executionContext: ExecutionContext) extends BaseRepository[User](dbConfigProvider, executionContext) {

  import profile.api._

  protected class UserTable(tag: Tag) extends BaseTable(tag, "user") {
    def firstname = column[String]("firstname")
    def lastname = column[String]("lastname")
    def password = column[String]("password")
    def * = (id, firstname, lastname, password, createdAt, updatedAt, deletedAt) <> (User.tupled, User.unapply)
  }

  protected val query = TableQuery[UserTable]
}

1 个答案:

答案 0 :(得分:0)

pamus评论让我朝着正确的方向前进。

我通过将内部Table-Class移动到自己的类并将存储库的查询作为构造函数参数来解决以下问题。

abstract class BaseRepository[E <: BaseEntity, T <: BaseTable[E]](val dbConfigProvider: DatabaseConfigProvider, executionContext: ExecutionContext, query: TableQuery[T]) extends HasDatabaseConfigProvider[JdbcProfile] {
  def all(): Future[Seq[E]] = db.run(query.result)
  def find(id: Long): Future[Option[E]] = db.run(query.filter(_.id === id).result.headOption)
}

class UserRepository @Inject()(dbConfigProvider: DatabaseConfigProvider)(implicit executionContext: ExecutionContext) extends BaseRepository[User, UserTable](dbConfigProvider, executionContext, TableQuery[UserTable]) {

}
abstract class BaseTable[E <: BaseEntity](tag: Tag, tableName: String) extends Table[E](tag, tableName) {
  implicit val localDateTimeToTimestamp: BaseColumnType[LocalDateTime] = MappedColumnType.base[LocalDateTime, Timestamp](
    l => Timestamp.valueOf(l),
    t => t.toLocalDateTime
  )
  def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
  def createdAt = column[LocalDateTime]("created_at")
  def updatedAt = column[LocalDateTime]("updated_at")
  def deletedAt = column[Option[LocalDateTime]]("deleted_at", O.Default(null))
}
class UserTable(tag: Tag) extends BaseTable[User](tag, "user") {
  def firstname = column[String]("firstname")
  def lastname = column[String]("lastname")
  def password = column[String]("password")
  def * = (id, firstname, lastname, password, createdAt, updatedAt, deletedAt) <> (User.tupled, User.unapply)
}

然后,我可以使用BaseRepository中的查询,如此

userRepository.find(1).map { user =>
  Ok(Json.toJson(user))
}