【问题标题】:Filter query based on sum of LocalDate and Option[Int] in Slick根据 Slick 中 LocalDate 和 Option[Int] 的总和过滤查询
【发布时间】:2017-03-03 07:33:30
【问题描述】:

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

startDate -> date type
duration -> nullable integer

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

现在,我想编写一个查询,给出一个日期givenDate,它会返回定义durationstartDate + 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

【问题讨论】:

  • stackoverflow.com/questions/21349547/…看看这个问题,可能对你有帮助
  • @KamilBanaszczyk 不幸的是,这没有帮助。我可以比较日期(正如我提到的,我使用的是slick-joda-mapper)。我不能做的是修改查询中的日期,然后进行比较。
  • 我不知道 slick-joda-mapper 是如何工作的,但是您是否尝试过将 givenDate 包装在 Rep 中?也许然后它将允许对 Rep[Int] 执行操作?

标签: scala jodatime slick slick-3.0


【解决方案1】:

好的,我找到了您问题的答案。所以基本上你不能解开 Rep,因为数据库类型安全。另外,您没有任何机会调用 inside 数据库引擎的 scala 函数,这就是我们不能以任何方式使用 minusDays(t.duration.getOrElse(0)) 的原因。由于不同的数据库引擎,Slick 也没有目的对每种数据类型实现 every 操作。但是如果你想在你的数据库上调用日期操作,你必须检查它是否支持日期操作。我的示例是在 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 包装的值,并且它将允许 slick 保留其类型安全的实现。

通过这些测试:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-03-24
    • 2020-06-23
    • 1970-01-01
    • 2015-09-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多