加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

postgresql – Slick 2.0 Generic CRUD操作

发布时间:2020-12-13 16:31:14 所属栏目:百科 来源:网络整理
导读:我一直在寻找如何为公共CRUD和其他类型的操作实现通用特性,我查看了 this和 this,并且指定的方法运行良好. 我想要的是一个通用的插入方法,我的类目前看起来像这样(非泛型实现): object CampaignModel { val campaigns = TableQuery[Campaign] def insert(ca
我一直在寻找如何为公共CRUD和其他类型的操作实现通用特性,我查看了 this和 this,并且指定的方法运行良好.

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

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但是我的知识非常基础而且我无法绕过类型,我尝试了T和A并且编译器说classtype不符合特质一个人.

其他信息,这些表是使用光滑的表生成工具生成的

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")
}
我设法让它工作,这是我的通用特性:
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字段的抽象类,这个带有上限约束对于获取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,CampaignRow.unapply)

  def ? = (id.?,(_: Any) => throw new Exception("Inserting into ? projection not supported."))

  override val id: Column[Long] = column[Long]("id",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"))
   }
 }

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读