我正在使用scala
,play
,sclick
;和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%';
}
}
定义GenericEntity
,id
,created
。
那么我应该使用updated
和getMonthlyOrder
为year
函数编写什么代码?
答案 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")
}
}