如何在Play-SLICK中过滤保存为即时的日期?

时间:2016-07-18 06:45:46

标签: postgresql scala playframework slick

我正在使用scalaplaysclick;和postgres。我制作了一张名为order&的桌子。它包含一个名为created的字段,其时间戳格式为zone。现在,我想根据order使用参数created& year如下: -

month

以上查询在postgres中工作正常。

我为SELECT * FROM "order" WHERE created::text LIKE '2016-07%'; 编写的scala代码是: -

Order

case class Order(id: Option[Int], customerId: Int, amount: Double, created: Option[Instant], updated: Option[Instant]) extends GenericEntity { def this(customerId: Int, amount: Double,) = this(None, customerId, amount, None, None) } class OrderTable(tag: Tag) extends GenericTable[Order](tag, "order") { override def id = column[Option[Int]]("id", O.PrimaryKey, O.AutoInc) def customerId = column[Int]("customer_id") def amount = column[Dount]("amount") def customer = foreignKey("fk_order_customer", customerId, Customers.table)(_.id.getOrElse(1), onUpdate = ForeignKeyAction.Restrict, onDelete = ForeignKeyAction.Cascade) def * = (id, customerId, amount, created, updated) <> ((Order.apply _).tupled, Order.unapply) } object Orders extends GenericService[Order, OrderTable] { override val table = TableQuery[OrderTable] override def copyEntityFields(entity: Order, id: Option[Int], created: Option[Instant], updated: Option[Instant]): Order = { entity.copy(id = id, created = created, updated = updated) } def getMonthlyOrder(year:Int, month: Int) = { // execute LIKE query for the following query // SELECT * FROM "order" // WHERE created::text LIKE '2016-07%'; } } 定义GenericEntityidcreated

那么我应该使用updatedgetMonthlyOrderyear函数编写什么代码?

1 个答案:

答案 0 :(得分:1)

你需要两件事:

1)一种列类型,让Slick知道如何将Instant持久化到数据库。在这种情况下,您希望将Instant映射到java.sql.Timestamp,Slick可以本机使用它。

implicit val instantColumnType: BaseColumnType[Instant] =
    MappedColumnType.base[Instant, Timestamp](
        instant => Timestamp.from(instant),
        ts => ts.toInstant
    )

2)从时间戳中提取年份和月份的功能。在这里,我使用了另一种方法而不是LIKE查询。您还可以定义从Instant到String的映射,并使用类似startsWith。

的内容
val yearFn = SimpleFunction.unary[Instant, Int]("year")
val monthFn = SimpleFunction.unary[Instant, Int]("month")

然后你会在getMonthlyOrder中使用它们,就像这样

def getMonthlyOrder(year: Int, month: Int): Future[Seq[Order]] = {
    val query = table.filter(_.created.map((created) => yearFn(created) === year && monthFn(created) === month))
    db.run(query.result)
}

对Slick 3.1有效的完整代码:

import java.sql.Timestamp
import java.time.Instant
import javax.inject.{Inject, Singleton}

import play.api.db.slick.{DatabaseConfigProvider, HasDatabaseConfigProvider}
import slick.driver.JdbcProfile
import slick.lifted.TableQuery

import scala.concurrent.Future

case class Order(id: Int,
                 customerId: Int,
                 amount: Double,
                 created: Option[Instant],
                 updated: Option[Instant])
@Singleton
class Orders @Inject()(val dbConfigProvider: DatabaseConfigProvider) extends HasDatabaseConfigProvider[JdbcProfile] {
    val table = TableQuery[OrderTable]

    import driver.api._

    implicit val instantColumnType: BaseColumnType[Instant] =
        MappedColumnType.base[Instant, Timestamp](
            instant => Timestamp.from(instant),
            ts => ts.toInstant
        )

    val yearFn = SimpleFunction.unary[Instant, Int]("year")
    val monthFn = SimpleFunction.unary[Instant, Int]("month")

    def getMonthlyOrder(year: Int, month: Int): Future[Seq[Order]] = {
        val query = table.filter(_.created.map((created) => yearFn(created) === year && monthFn(created) === month))
        db.run(query.result)
    }

    class OrderTable(tag: Tag) extends Table[Order](tag, "ORDERS") {

        def * = (id, customerId, amount, created, updated) <> ((Order.apply _).tupled, Order.unapply)

        def id = column[Int]("ID", O.PrimaryKey, O.AutoInc)

        def customerId = column[Int]("CUSTOMER_ID")

        def amount = column[Double]("AMOUNT")

        def created = column[Option[Instant]]("CREATED")

        def updated = column[Option[Instant]]("UPDATED")
    }

}