在Slick中基于LocalDate和Option [Int]之和过滤查询

时间:2017-03-03 07:33:30

标签: scala jodatime slick slick-3.0

我有一个包含两列的数据库表:

startDate -> date type
duration -> nullable integer

在我的Slick配置中,这些列分别定义为LocalDate(我使用Joda)和Option[Int]

现在,我想写一个给定日期givenDate的查询,它会返回所有定义duration的行和startDate + duration < givenDate

我期待这样的事情:

db.run(table.filter(t => {
  t.duration.isDefined && 
  t.startDate < givenDate.minusDays(t.duration.getOrElse(0))
}))

不幸的是,这不起作用,因为t.duration.getOrElse(0)实际上不是整数,而是Rep[Int]

我该怎么做?

我使用的技术:Scala,Slick 3.1,Joda Time,slick-joda-mapper

1 个答案:

答案 0 :(得分:0)

好的,我已经找到了你问题的答案。因此,基本上您无法解包Rep,因为数据库类型安全。另外,您没有机会调用scala函数内部数据库引擎,这就是我们无法以任何方式使用minusDays(t.duration.getOrElse(0))的原因。由于不同的数据库引擎,Slick还没有目的在每种数据类型上实现每个操作。但是,如果要在数据库上调用日期操作,则必须检查它是否支持日期操作。我的例子是关于H2数据库,我们在这里:

定义数据

case class DateTest(id: Option[Int] = None, date: LocalDate, duration: Int) extends BaseEntity

  class DateTestTable(tag: Tag) extends BaseTable[DateTest](tag, None, "DateTest") {

    override val id: Rep[Option[Int]] = column[Option[Int]]("id", O.PrimaryKey, O.AutoInc)

    def date: Rep[LocalDate] = column[LocalDate]("date")

    def duration = column[Int]("duration")

    def * = (id, date, duration) <>(DateTest.tupled, DateTest.unapply)

  }

  val dateTests: TableQuery[DateTestTable] = TableQuery[DateTestTable]

插入数据

H2Connector.dateTests ++= Seq(
  DateTest(Some(1), new LocalDate(2017,3,4),15),
  DateTest(Some(2), new LocalDate(2017,2,17),15)
)

<强>存储库

  val addDays: (Rep[String], Rep[Int], Rep[LocalDate]) => Rep[LocalDate] = SimpleFunction.ternary[String,Int,LocalDate,LocalDate]("DATEADD")

  def dateWithDuration(givenDate: LocalDate): Future[Seq[DateTest]] ={
    filter(auth => auth.date < addDays("DAY",auth.duration*(-1),givenDate))
  }

因此,在最后一段代码中,您可以看到它是如何实现的。首先,H2支持日期DATEADD上的此操作,Slick允许您实现自定义函数,该函数将使用数据库函数。通过这种方式,您可以使用REP包装的值,并且它将允许光滑保持其类型安全实现。

通过这些测试:

  "TestDate " should {
    "return date with small duration " in {
      println(waitForResult(testDate.dateWithDuration(new LocalDate(2017,3,15))))
    }
    "return every date " in {
      println(waitForResult(testDate.getAll))
    }
  }

结果是:

Vector(DateTest(Some(2),2017-02-17,15))
Vector(DateTest(Some(1),2017-03-04,15), DateTest(Some(2),2017-02-17,15))