【问题标题】:Slick 2.0 Generic CRUD operationsSlick 2.0 通用 CRUD 操作
【发布时间】:2014-06-14 05:57:33
【问题描述】:

我一直在寻找如何为公共 CRUD 和其他类型的操作实现通用特征,我查看了 thisthis 并且指定的方法运行良好。

我想要的是一个通用的插入方法,我的类目前看起来像这样(非通用实现):

object CampaignModel {
  val campaigns = TableQuery[Campaign]

  def insert(campaign: CampaignRow)(implicit s: Session) = {
    campaigns.insert(campaign)
  }
}

到目前为止,我在第一个链接之后尝试过的是(通用实现):

trait PostgresGeneric[T <: Table[A], A]  {
  val tableReference = TableQuery[T]

  def insertGeneric(row: ? What type goes here ?)(implicit s: Session) = tableReference.insert(row)

}

当我检查 insert 方法时,看起来正确的类型应该是 T#TableElementType 但我的知识非常基础,我无法理解类型,我尝试了 TA 和编译器说类类型不符合 trait one 的。

其他信息,表格是用光滑的表格生成工具生成的

case class CampaignRow(id: Long, name: Option[String])

/** Table description of table campaign. Objects of this class serve as prototypes for rows in queries. */
class Campaign(tag: Tag) extends Table[CampaignRow](tag, "campaign") {
  def * = (id, name) <>(CampaignRow.tupled, CampaignRow.unapply)

  /** Maps whole row to an option. Useful for outer joins. */
  def ? = (id.?, name).shaped.<>({
    r => import r._; _1.map(_ => CampaignRow.tupled((_1.get, _2)))
  }, (_: Any) => throw new Exception("Inserting into ? projection not supported."))

  /** Database column id AutoInc, PrimaryKey */
  val id: Column[Long] = column[Long]("id", O.AutoInc, O.PrimaryKey)
  /** Database column name  */
  val name: Column[Option[String]] = column[Option[String]]("name")
}

【问题讨论】:

    标签: postgresql scala generics slick slick-2.0


    【解决方案1】:

    我设法让它发挥作用,这是我的一般特征:

    import scala.slick.driver.PostgresDriver
    import scala.slick.driver.PostgresDriver.simple._
    import path.to.RichTable
    
    trait PostgresGeneric[T <: RichTable[A], A] {
    
      val tableReference: TableQuery[T]
    
      def insert(row: T#TableElementType)(implicit s: Session) = 
        tableReference.insert(row)
    
      def insertAndGetId(row: T#TableElementType)(implicit s: Session) = 
        (tableReference returning tableReference.map(_.id)) += row
    
      def deleteById(id: Long)(implicit s: Session): Boolean = 
        tableReference.filter(_.id === id).delete == 1
    
      def updateById(id: Long, row: T#TableElementType)(implicit s: Session): Boolean = 
        tableReference.filter(_.id === id).update(row) == 1
    
      def selectById(id: Long)(implicit s: Session): Option[T#TableElementType] = 
        tableReference.filter(_.id === id).firstOption
    
      def existsById(id: Long)(implicit s: Session): Boolean = {
        (for {
          row <- tableReference
          if row.id === id
        } yield row).firstOption.isDefined
      }
    }
    

    RichTable 是一个带有 id 字段的抽象类,具有上限约束的 this 可用于获取 T#TableElementType 的 id 字段(有关更多信息,请参阅this):

    import scala.slick.driver.PostgresDriver.simple._
    import scala.slick.jdbc.{GetResult => GR}
    
    abstract class RichTable[T](tag: Tag, name: String) extends Table[T](tag, name) {
      val id: Column[Long] = column[Long]("id", O.PrimaryKey, O.AutoInc)
    }
    

    我的广告系列表现在看起来像这样:

    import scala.slick.driver.PostgresDriver.simple._
    import scala.slick.jdbc.{GetResult => GR}
    import scala.slick.lifted.TableQuery
    
    case class CampaignRow(id: Long, name: Option[String])
    
    class Campaign(tag: Tag) extends RichTable[CampaignRow](tag, "campaign") {
      def * = (id, name) <>(CampaignRow.tupled, CampaignRow.unapply)
    
      def ? = (id.?, name).shaped.<>({
        r => import r._; _1.map(_ => CampaignRow.tupled((_1.get, _2)))
      }, (_: Any) => throw new Exception("Inserting into ? projection not supported."))
    
      override val id: Column[Long] = column[Long]("id", O.AutoInc, O.PrimaryKey)
      val name: Column[Option[String]] = column[Option[String]]("name")
    }
    

    实现泛型特征的模型如下所示:

     object CampaignModel extends PostgresGeneric[Campaign, CampaignRow] {
    
       override val tableReference: PostgresDriver.simple.TableQuery[Tables.Campaign] = 
         TableQuery[Campaign]
    
       def insertCampaign(row: CampaignRow) = {
         insert(CampaignRow(0, "test"))
       }
     }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-06-28
      • 2011-02-08
      • 1970-01-01
      • 1970-01-01
      • 2018-06-14
      • 1970-01-01
      • 1970-01-01
      • 2016-12-16
      相关资源
      最近更新 更多