【问题标题】:Nullable column causes SlickException when trying to write null value尝试写入空值时可空列导致 SlickException
【发布时间】:2018-07-04 09:49:55
【问题描述】:

在我的 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)
}

在进化脚本中创建表:

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 解释为不可为空。

我的配置中是否缺少某些内容,或者这可能是一个错误?

(无论如何,我根本找不到任何使用可为空列的 Slick 3.x 示例/种子项目。)


更新:谜团解开

经过进一步调查,事实证明我一直在寻找错误的地方。

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

我将把这个问题留到后面,所以投资类似问题的人可以从我的错误中吸取教训。

【问题讨论】:

    标签: scala playframework slick


    【解决方案1】:

    你能改变你的柱形吗:

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

    到:

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

    另外,将 passwordId def 中的选项 [Long] 删除为 Long?

    【讨论】:

    • 我试过了,但结果完全相同。我不确定,但我认为 Slick 平等对待这两种表示形式,因为 .? 将一列提升为选项。
    • 设置一个默认值怎么样? O.Default(None) 到 passwordId def?
    • 嗯,同样的结果。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-11-29
    • 2021-11-18
    • 1970-01-01
    • 2020-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多