我有一个包含两列的数据库表:
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
答案 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))