我正在使用Play Framework 2.6和光滑的3.2.1创建一个Web应用程序。 当我尝试将记录插入“USER”表时,其中created_at列中包含“NOT NULL DEFAULT CURRENT_TIMESTAMP”(我正在使用MySQL),数据库会抛出错误“Column'creved_at'不能为空”。
我知道光滑生成的SQL是错误的。该语句试图将null插入到created_at列中。让光滑生成不包含created_at列的SQL的正确方法是什么?
scala代码的摘录。
import org.joda.time.DateTime
case class User(
id: Option[Long],
accountId: Long,
name: String,
description: Option[String] = None,
createdAt: Option[DateTime: = None,
)
class UserTable(tag: Tag) extends Table[User](tag, "user") {
def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
def accountId = column[Long]("account_id")
def name = column[String]("name")
def description = column[Option[String]]("description")
def createdAt = column[Option[DateTime]]("created_at")
def * = (id.?, accountId, name, description, createdAt) <> (User.tupled, User.unapply)
}
object Users extends TableQuery(new UserTable(_)) {
}
val user = User(None, accountId, name, description)
val insert = for {
newId <- (Users returning Users.map(_.id)) += user
} yield newId
db.run(insert)
生成SQL
[debug] s.j.J.statement - Preparing insert statement (returning: id): insert into `user` (`account_id`,`name`,`description`,`created_at`) values (?,?,?,?)
[debug] s.j.J.parameter - /------+--------+---------+-----------\
[debug] s.j.J.parameter - | 1 | 2 | 3 | 4 |
[debug] s.j.J.parameter - | Long | String | VARCHAR | TIMESTAMP |
[debug] s.j.J.parameter - |------+--------+---------+-----------|
[debug] s.j.J.parameter - | 1 | user01 | NULL | NULL |
[debug] s.j.J.parameter - \------+--------+---------+-----------/
答案 0 :(得分:1)
重新思考你的榜样。您的表格不接受null
作为列created_at
的值。但是,您的域模型允许此字段可以是None
,不能以null
之外的任何其他方式在数据库中表示。因此,如果您希望光滑生成正确的查询,则必须将created_at
的类型更改为DateTime
。
答案 1 :(得分:0)
createdAt
不能是Option
,您可以放置DateTime.now
以避免使用Option
。此外,还需要DateTime
列映射器:
import slick.lifted.MappedTypeMapper
import java.sql.Date
import org.joda.time.DateTime
import slick.lifted.TypeMapper.DateTypeMapper
object DateTimeMapper {
implicit def date2dt = MappedTypeMapper.base[DateTime, Date] (
dt => new Date(dt.getMillis),
date => new DateTime(date)
)
}
或者您很可能需要Timestamp
,而不是Date
:
implicit def dateTime =
MappedColumnType.base[DateTime, Timestamp](
dt => new Timestamp(dt.getMillis),
ts => new DateTime(ts.getTime)
)
如果你不想处理DateTime.now
,你可能会这样做:
def created = column[DateTime]("createdAt", SqlType("timestamp not null default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP"))
此处的其他信息: http://queirozf.com/entries/scala-slick-dealing-with-datetime-timestamp-attributes
答案 2 :(得分:0)
如果你看一下你的投影,你必须抬起created_at
,就像你抬起你的身份一样。
所以你的预测会变成:
def * = (id.?, accountId, name, description, createdAt.?) <> (User.tupled, User.unapply)
在createdAt。
之后注意.?