浮油2.0通用CRUD操作 [英] Slick 2.0 Generic CRUD operations

查看:105
本文介绍了浮油2.0通用CRUD操作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在考虑如何实现commons CRUD和其他类型操作的通用特性,我查看了这个

I've been looking around on how to implement a generic trait for commons CRUD and other kinds of operations, I looked at this and this and the method specified are working well.

我想要的是一个通用的插入方法,我的类(非泛型实现):

What I would like to have is a generic method for insertion, my class looks like this at the moment (non generic implementation):

object CampaignModel {
  val campaigns = TableQuery[Campaign]

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

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

What I tried so far, following the first link, was this (generic implementation):

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

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

}

当我检查插入方法时,它看起来像正确的类型应该是 T#TableElementType 但我的知识是非常基本的,我无法环绕类型,我尝试了 T A ,并且编译器说这个classtype不符合这个特性。

When I inspect the insert method it looks like the right type should be T#TableElementType but my knowledge is pretty basic and I can't wrap my head around types, I tried T and A and the compiler says that the classtype does not conform to the trait one's.

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

Other infos, the tables are generated with the slick table generation tools

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")
}


推荐答案

我设法让它工作,这是我的通用特质:

I managed to make it work, this is my generic trait:

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字段很有用(参见以获取更多信息):

Where RichTable is an abstract class with an id field, this, with the upper bound constraint is useful to get the id field of T#TableElementType (see this for more info):

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)
}

我的广告系列表现在如下所示:

And my campaign table now looks like this:

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")
}

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

The model implementing the generic trait looks like this:

 object CampaignModel extends PostgresGeneric[Campaign, CampaignRow] {

   override val tableReference: PostgresDriver.simple.TableQuery[Tables.Campaign] = 
     TableQuery[Campaign]

   def insertCampaign(row: CampaignRow) = {
     insert(CampaignRow(0, "test"))
   }
 }

这篇关于浮油2.0通用CRUD操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆