微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用Slick插入具有自动递增ID的值的常见存储库/ DAO方法缺少隐式

如何解决使用Slick插入具有自动递增ID的值的常见存储库/ DAO方法缺少隐式

我对Scala并不陌生,尝试学习 slick ,并从play-slick-example开始,一切都可以理解。

我开始创建自己的实体,表和查询。 第一个技巧是解决在插入时获得自动递增的id的问题,但是示例代码可以解决这个问题,尽管习惯用法可能有所改进。 解决的下一件事是将所有通用代码移到一个位置。通用代码是指基本的CRUD操作,基本上对所有实体都进行复制粘贴。 于是我去创建了基础Entity

trait Entity[T <: Entity[T,ID],ID] {
  val id: Option[ID]    
  def withId(id: ID): T
}

接下来,我创建了BaseRepo,其中应包含所有通用代码

abstract class BaseRepo[T <: Entity[T,ID] {    
  protected val dbConfigProvider: DatabaseConfigProvider
  val dbConfig = dbConfigProvider.get[JdbcProfile]

  import dbConfig._
  import profile.api._

  type TableType <: Keyed[ID] with RelationalProfile#Table[T]

  protected val tableQuery: TableQuery[TableType]
}

dbConfigProvider注入到实现中,并允许导入正确的配置(不确定是否需要它,但是示例具有这样的含义)。 Keyed是另一个特征,它用列Table表示id

trait Keyed[ID] {
  def id: Rep[ID]
}

目前看来一切都很好。要扩展BaseRepo,将需要适当地分配TableTypetableQuery,并且一切正常。 我从以下实现开始:

case class Vehicle(override val id: Option[Long],name: String,plate: String,modelId: Long)
  extends Entity[Vehicle,Long] {
  override def withId(id: Long): Vehicle = this.copy(id = Some(id))
}

以及以下回购:

@Singleton
class VehicleRepository @Inject()(override val dbConfigProvider: DatabaseConfigProvider)
                                 (implicit ec: ExecutionContext) 
  extends BaseRepo [Vehicle,Long]{

  import dbConfig._
  import profile.api._

  type TableType = Vehicles
  val tableQuery = TableQuery[Vehicles]

  class Vehicles(tag:Tag) extends Table[Vehicle](tag:Tag,"vehicles") with Keyed[Long] {
    def id = column[Long]("id",O.PrimaryKey,O.AutoInc)
    def name = column[String]("name")
    def plate = column[String]("plate")
    def modelId = column[Long]("modelId")

    def * = (id.?,name,plate,modelId) <> ((Vehicle.apply _).tupled,Vehicle.unapply)
  }

一切仍然看起来不错! 现在,我将all()添加到BaseRepo:

  def all() = db.run {
    tableQuery.result
  }

它有效!我可以使用简单的Vehicle通过注入的repo:VehicleRepository列出我所有的repo.all()实体(好吧,我确切地说是Future,但谁在乎)

接下来,我去尝试使用自动递增的ID概括化插入,并将其放入BaseRepo

def create(item: T,ec:ExecutionContext) = db.run{
    ((tableQuery returning tableQuery.map(_.id)) += item)
      .map(id => item.withId(id))(ec)
  }

在这里不要介意ExecutionContext,但是无论如何,这是行不通的,并且错误让我很沮丧:

Slick does not kNow how to map the given types.
Possible causes: T in Table[T] does not match your * projection,you use an unsupported type in a Query (e.g. scala List),or you forgot to import a driver api into scope.
  required level: slick.lifted.FlatShapeLevel
     Source type: slick.lifted.Rep[ID]
   Unpacked type: T
     Packed type: G
]

如果我将此方法移回到VehicleRepository中(用T代替Vehicle,则一切都像是一种魅力。

经过数小时的挖掘,我了解到tableQuery.map使用一些(implicit shape: Shape[_ <: FlatShapeLevel,F,T,G])作为隐式参数,而我实际上不知道VehicleRepository的范围是哪里来的,为什么呢?在我的BaseRepo

中不可用

任何有关如何解决此问题的建议或建议,或者其他一些使用Slick概括CRUD的方法,都将适用!

我正在使用Play-2.8 Slick-3.3.2 play-slick-5.0.0 scala-2.13.1

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。