播放Scala&;第三,得到;第xx列不能为空";在带有“的列中出错”;非空默认当前“U时间戳”;
我正在使用Play Framework 2.6和slick 3.2.1创建一个web应用程序。 当我尝试将一条记录插入到表“USER”中时,该表创建了带有“notnull DEFAULT CURRENT\u TIMESTAMP”的列(我使用的是MySQL),数据库抛出一个错误“column'created\u at'cannot NULL” 我知道slick生成的SQL是错误的。该语句试图将null插入到已创建的_at列中。让slick生成不包含created_at列的SQL的正确方法是什么 scala代码摘录。播放Scala&;第三,得到;第xx列不能为空";在带有“的列中出错”;非空默认当前“U时间戳”;,scala,playframework,slick,slick-3.0,Scala,Playframework,Slick,Slick 3.0,我正在使用Play Framework 2.6和slick 3.2.1创建一个web应用程序。 当我尝试将一条记录插入到表“USER”中时,该表创建了带有“notnull DEFAULT CURRENT\u TIMESTAMP”的列(我使用的是MySQL),数据库抛出一个错误“column'created\u at'cannot NULL” 我知道slick生成的SQL是错误的。该语句试图将null插入到已创建的_at列中。让slick生成不包含created_at列的SQL的正确方法是什么 s
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)
重新思考你的例子。您的表不接受
null
作为在创建的列的值。但您的域模型允许此字段可以是None
,它不能在数据库中以null
以外的任何方式表示。因此,如果您希望slick生成正确的查询,您必须将在
处创建的的类型更改为DateTimecreatedAt
不能是选项
,您可以将日期时间放在那里。现在
可以避免使用选项
。还需要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)
)
}
或者您很可能需要它作为时间戳
,而不是日期
:
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"))
其他信息如下:
如果你看你的投影,你必须抬起在
创建的,就像抬起你的id一样
所以你的预测会变成:
def*=(id.?,accountId,name,description,createdAt.?)(User.tuple,User.unapply)
注意createdAt之后的?
。我找到了两种解决这个问题的方法(使用Slick 3.2.3)。幸运的是,对于我的用例,我没有使用Slick创建表或生成表类,因此我并不真正关心它将生成的模式是否有效
假设我们有一个简单的用户模型/表:
case class User(id: Long, name: String, createdAt: Timestamp, updatedAt: Timestamp)
class UsersDAO(tag: Tag) extends Table[User](tag, "users") {
def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
def name = column[String]("name")
def createdAt = column[Timestamp]("created_at", O.AutoInc)
def updatedAt = column[Timestamp]("updated_at", O.AutoInc)
override def * = (id, name, createdAt, updatedAt) <>
(User.tupled, User.unapply)
}
选项2:将字段标记为O.AutoInc
如果使用O.AutoInc
标记createdAt
和updatedAt
列(如上所述),只需使用+=
语法即可:
object UsersDAO extends TableQuery(new UsersDAO(_)) {
def create(u: User) = this returning this.map(_.id) += user
}
目前似乎有几个问题与此相关。希望一旦他们解决了,会有更好的办法。
这样,您的意思是我必须编写User(None,accountId,name,description,new DateTime())
来创建要插入的用户实例,并且表上的修饰符DEFAULT CURRENT_TIMESTAMP
永远不会与slick一起使用吗?在您的情况下,是的,它不会被使用。是否有可能以你想要的方式实施,我现在还不知道。考虑一下:在表定义中可以实现默认值,但我不确定。
object UsersDAO extends TableQuery(new UsersDAO(_)) {
def create(u: User) = this map { c =>
(c.name) // only include columns you want to send
} returning this.map(_.id) += (u.name)
}
object UsersDAO extends TableQuery(new UsersDAO(_)) {
def create(u: User) = this returning this.map(_.id) += user
}