scala - 可空列在尝试写入空值时导致 SlickException

标签 scala playframework slick

在我的 Play + Slick 3.2.1(使用 PlaySlick 3.0.0)项目中,我试图在表 user 上有一个可为空的列 password_id:

case class User(id: Long, name: String, passwordId: Option[Long]) extends Identity

class UserTable(tag: Tag) extends Table[User](tag, "user") {
  def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
  def name = column[String]("name", O.Unique)
  def passwordId = column[Option[Long]]("password_id", O.Unique)
  def password = foreignKey("password", passwordId, Passwords.passwords)(_.id)

  override def * = (id, name, passwordId) <> (User.tupled, User.unapply)
}

在 evolutions 脚本中创建表:

create table user (
  id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR NOT NULL UNIQUE,
  password_id BIGINT UNIQUE,
  FOREIGN KEY(password_id) REFERENCES password(id)
);

现在,当我尝试按如下方式将新用户插入该表时

def dbConfig = DatabaseConfigProvider.get[JdbcProfile](Play.current)
dbConfig.db.run(users += User(0, "test", None))

我遇到了一个异常:

slick.SlickException: Read NULL value (null) for ResultSet column <computed>
at slick.jdbc.SpecializedJdbcResultConverter$$anon$1.read(SpecializedJdbcResultConverters.scala:27)
at slick.jdbc.SpecializedJdbcResultConverter$$anon$1.read(SpecializedJdbcResultConverters.scala:24)
at slick.relational.ProductResultConverter.read(ResultConverter.scala:56)
at slick.relational.ProductResultConverter.read(ResultConverter.scala:46)
at slick.relational.TypeMappingResultConverter.read(ResultConverter.scala:136)
at slick.jdbc.JdbcInvokerComponent$QueryInvokerImpl.extractValue(JdbcInvokerComponent.scala:36)
at slick.jdbc.StatementInvoker$$anon$1.extractValue(StatementInvoker.scala:67)
at slick.jdbc.PositionedResultIterator.fetchNext(PositionedResult.scala:176)
at slick.util.ReadAheadIterator.update(ReadAheadIterator.scala:28)
at slick.util.ReadAheadIterator.hasNext(ReadAheadIterator.scala:34)
...

对我来说,这表明 Slick 仍然将 password_id 解释为不可为 null。

我的配置中是否遗漏了什么,或者这可能是一个错误?

(就其值(value)而言,我根本找不到任何使用可空列的 Slick 3.x 示例/种子项目。)


更新:谜团解开了

经过进一步调查,我发现我找错地方了。

有一个不同的表,其属性未声明为可为 null(即 Option[...]),但意外地被提供了一个 null 值。由于数据库操作的异步性质以及这两者几乎同时发生的事实,我在调试时错误地得出了上述假设。公平地说,错误堆栈跟踪也不是很有帮助。

我只是把这个问题留作后验,所以投资类似问题的人可以从我的错误中吸取教训。

最佳答案

你能改变你的列形状吗:

 override def * = (id, name, passwordId) <> (User.tupled, User.unapply)

到:

 override def * = (id, name, passwordId.?) <> (User.tupled, User.unapply)

另外,从 passwordId def 中删除选项 [Long] 到 Long?

关于scala - 可空列在尝试写入空值时导致 SlickException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48437919/

相关文章:

scala - 使用空格来对齐代码是否被认为是一种好的风格?

java - 可以在Gradle中混合.java和.clojure和.scala文件

java - Mac OS X Activator New Play Framework 错误

scala - 为什么 Slick 需要使用三个等号 (===) 进行比较?

eclipse - 如何在 Eclipse IDE 中运行 scala BDD 测试

scala - For 循环 Scala 的快速功能等效项

scala - 使用 Play 和 Slick 时,我应该如何处理数据库演变?我必须手动编写 SQL 吗?

scala - Play 剪影未将密码插入数据库表

scala - 光滑的 3 个多个外部连接

scala - Slick中的inSet和inSetBind有什么区别