跨不同的 TableQuery[T] 实现通用功能

Implementing common functionality across different TableQuery[T]

正在寻找有关以下是否可能的指导:

我有以下实用函数,是我专门为我的 classes (ContentCollectionFilter) 之一创建的:

    def updateFilters(updatedFilters: List[ContentCollectionFilter]) = {
      DBIO.sequence(updatedFilters.map { 
        theFilter => {
          TableQuery[ContentCollectionFilterTable].filter(_.id === filter.id.toString()).update(theFilter)
        }
      })
    }

我的ContentCollectionFilter是这样定义的:

final case class ContentCollectionFilter(
        id:           UUID,
        collectionId: UUID,
        filterType:   CollectionFilterType,
        filterValue:  String
)

我真的很想让这个函数对任何具有 id 字段的 class 通用。

我应该能够创建一个名为 ModelWithId 的特征,让我的 ContentCollectionFilter 扩展它,然后将其传递到更通用的函数中,如下所示:

def updateIt(toUpdate: List[ModelWithId])

但是我还需要概括一下:

  1. 在函数内部使用哪个TableQuery[...](隐式查找?)
  2. 传递给 TableQuery 的 update(...) 的参数类型,因为我不认为它会接受 ModelWithId 类型的参数,它需要是特定于 class ContentCollectionFilterTable

供参考,ContentCollectionFilterTable定义如下:

class ContentCollectionFilterTable(tag: Tag) extends Table[ContentCollectionFilter] (tag, "collection_filter") { ... }

P.S. 我正在使用 Slick 3.3.3 和 Scala 2.13.3

得出如下结论:

创建了 ModelWithId 特征..

trait ModelWithId {
  def id: UUID
}

ContentCollectionFilter 扩展它:

final case class ContentCollectionFilter extends (
        override val id:  UUID,
           collectionId:  UUID,
             filterType:  CollectionFilterType,
            filterValue:  String
) extends ModelWithId

创建了一个 TableWithId 摘要 class:

abstract class TableWithId[T](tag: Tag, tableName: String) extends Table[T] (tag, tableName) {

  def id: Rep[String]

}

创建了一个 TableWithIdOps 特征:

trait TableWithIdOps[T <: TableWithId[E], E <: ModelWithId] {
  def query: TableQuery[T]
  def insert(insertObj:E) = {
    query += insertObj
  }
  
  def update(updateObj:E) = {
    query.filter(_.id === updateObj.id.toString).update(updateObj)
  }

}

创建了一个 ContentCollectionFilterTable 对象:

object ContentCollectionFilterTable extends TableWithIdOps[ContentCollectionFilterTable, ContentCollectionFilter] {
  override def query = TableQuery[ContentCollectionFilterTable]
}

更改了我现有的 ContentCollectionFilterTable 特征以扩展 TableWithId:

class ContentCollectionFilterTable(tag: Tag) extends TableWithId[ContentCollectionFilter] (tag, "collection_filter") {
  override def id = column[String]("id", O.PrimaryKey)
  def collectionId = column[String]("collection_id")
  def filterType = column[CollectionFilterType]("filter_type")
  def filterValue = column[String]("filter_value")  
  //...
}

用法:

def updateContentCollection(contentCollectionFilter: ContentCollectionFilter) = {
  val action = ContentCollectionTableFilter.update(contentCollectionFilter)
  Await.result(getDatabase.run(action), Duration.Inf)
}