Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 如何编写具有可空列的光滑表定义?_Scala_Playframework_Slick_Codegen - Fatal编程技术网

Scala 如何编写具有可空列的光滑表定义?

Scala 如何编写具有可空列的光滑表定义?,scala,playframework,slick,codegen,Scala,Playframework,Slick,Codegen,这个表定义一直有效,直到我意识到具有可为空的列意味着我需要使用选项[String],而不仅仅是String。这是我唯一做的更改,这就是我的代码现在的样子 class RespondentTableDef(tag: Tag) extends Table[Respondent](tag, "respondent") { def id = column[Long]("id", O.PrimaryKey) def uuid = column[String]("uuid") def vers

这个表定义一直有效,直到我意识到具有可为空的列意味着我需要使用选项[String],而不仅仅是String。这是我唯一做的更改,这就是我的代码现在的样子

class RespondentTableDef(tag: Tag) extends Table[Respondent](tag, "respondent") {

  def id = column[Long]("id", O.PrimaryKey)
  def uuid = column[String]("uuid")
  def version = column[Long]("version")
  def task = column[Long]("task")
  def firstName = column[Option[String]]("first_name")
  def lastName = column[Option[String]]("last_name")
  def ageGroup = column[Option[String]]("age_group")
  def incomeLevel = column[Option[String]]("income_level")
  def employmentStatus = column[Option[String]]("employment_status")
  def maritalStatus = column[Option[String]]("marital_status")
  def housingStatus = column[Option[String]]("housing_status")
  def educationStatus = column[Option[String]]("education_status")
  def gender = column[Option[String]]("gender")

  override def * =
    (id, uuid, version, task, firstName, lastName, ageGroup, incomeLevel, employmentStatus, maritalStatus, housingStatus, educationStatus, gender) <> (Respondent.tupled, Respondent.unapply)
}
class RespondentTableDef(tag:tag)扩展表[应答者](tag,“应答者”){
def id=列[Long](“id”,O.PrimaryKey)
def uuid=列[字符串](“uuid”)
def版本=列[长](“版本”)
def task=列[Long](“任务”)
def firstName=列[选项[字符串](“名字”)
def lastName=列[选项[字符串]](“姓氏”)
def ageGroup=列[选项[字符串](“年龄组”)
def incomeLevel=列[选项[字符串]](“收入水平”)
def employmentStatus=列[选项[字符串]](“就业状态”)
def maritalStatus=列[选项[字符串]](“婚姻状况”)
def housingStatus=列[选项[字符串](“外壳状态”)
def educationStatus=列[选项[字符串]](“教育状态”)
定义性别=列[选项[字符串]](“性别”)
超控def*=
(id、uuid、版本、任务、名、姓、年龄组、收入水平、就业状况、婚姻状况、住房状况、教育状况、性别)(被访者.tuple,被访者.unapply)
}
我在编译时遇到这个错误

[error] /Users/roy/adivinate/survey2/app/model/Respondent.scala:45: No matching Shape found.
[error] Slick does not know how to map the given types.
[error] Possible causes: T in Table[T] does not match your * projection. Or you use an unsupported type in a Query (e.g. scala List).
[error]   Required level: slick.lifted.FlatShapeLevel
[error]      Source type: (slick.lifted.Rep[Long], slick.lifted.Rep[String], slick.lifted.Rep[Long], slick.lifted.Rep[Long], slick.lifted.Rep[Option[String]], slick.lifted.Rep[Option[String]], slick.lifted.Rep[Option[String]], slick.lifted.Rep[Option[String]], slick.lifted.Rep[Option[String]], slick.lifted.Rep[Option[String]], slick.lifted.Rep[Option[String]], slick.lifted.Rep[Option[String]], slick.lifted.Rep[Option[String]])
[error]    Unpacked type: (Long, String, Long, Long, String, String, String, String, String, String, String, String, String)
[error]      Packed type: Any
[error]     (id, uuid, version, task, firstName, lastName, ageGroup, incomeLevel, employmentStatus, maritalStatus, housingStatus, educationStatus, gender) <> (Respondent.tupled, Respondent.unapply)
[error]                                                                                                                                                    ^
[error] one error found
[error] (compile:compileIncremental) Compilation failed
[error] Total time: 5 s, completed Dec 21, 2016 8:53:17 PM
[error]/Users/roy/adivinate/survey2/app/model/apper.scala:45:找不到匹配的形状。
[错误]Slick不知道如何映射给定的类型。
[错误]可能原因:表[T]中的T与您的*投影不匹配。或者在查询中使用不受支持的类型(例如scala列表)。
[错误]所需级别:slick.lifted.FlatShapeLevel
[错误]源类型:(slick.lifted.Rep[Long],slick.lifted.Rep[String],slick.lifted.Rep[Long],slick.lifted.Rep[Option[String]],slick.lifted.Rep[Option[String]],slick.lifted.Rep[Option[String]],slick.lifted.Rep[Option[String]],slick.Rep[Option[String]],slick.lifted.Rep.Rep[Option][Option[String]]、slick.lifted.Rep[Option[String]]、slick.lifted.Rep[Option[String]])
[错误]解包类型:(长,字符串,长,长,字符串,字符串,字符串,字符串,字符串,字符串,字符串,字符串,字符串,字符串,字符串,字符串)
[错误]打包类型:任意
[错误](id、uuid、版本、任务、名字、姓氏、年龄组、收入水平、就业状况、婚姻状况、住房状况、教育状况、性别)(被访者.tuple,被访者.unapply)
[错误]^
[错误]发现一个错误
[错误](编译:编译增量)编译失败
[错误]总时间:5秒,已完成2016年12月21日晚上8:53:17

这基本上是一件简单的事情-您的case类需要有这些字段可选。例如,您不需要(在您的case类中):
firstName:String
您应该有
firstName:Option[String]
在模型类中将您的字段声明为
Option[T]
而不是
T
,以使相应的列可为空

让我们用一个例子来理解这一点

case class Foo(name: String, rating: Option[Int])

class Foos(tag: Tag) extends Table[Foo](tag, "foos") {
  def name = column[String]("name") //name is not null
  def rating = column[Option[Int]]("rating") //rating is nullable
  def * = (name, rating) <> (Foo.tupled, Foo.unapply)
}
case类Foo(名称:String,评级:Option[Int])
类Foos(tag:tag)扩展表[Foo](tag,“Foos”){
def name=列[String](“name”)//名称不为空
def rating=column[Option[Int]](“rating”)//评级可为空
def*=(名称、等级)(Foo.tuple、Foo.unapply)
}
如果您想使某个字段可为null,只需将其声明为
选项
字段,slick就会理解并生成sql,将该特定字段作为null

上述设计与Scala选项设计是无缝的、合理的。意思是Scala中的选项直接转换为sql中的可空选项

在旧版本的Slick中


您必须通过在列声明中显式传递O.NotNull来告诉特定列不是null,但在新版本的slick中不需要它。请不要在列的定义中使用选项。如果您有选项[String],则列应该仍然是String

def firstName = column[Option[String]]("first_name") //Bad
def firstName = column[String]("first_name") //Good
定义选择(def*)时,使用。?定义选项

  override def * =
    (id, uuid, version, task, firstName.?, lastName.?, ageGroup.?, incomeLevel.?, employmentStatus.?, maritalStatus.?, housingStatus.?, educationStatus.?, gender.?) <> (Respondent.tupled, Respondent.unapply)

您可以分享一下为什么不应该在列定义中使用
选项
吗?如果列可为空,您必须使用选项。不,您应该在列方法类型参数中使用选项[String]。如果数据库在没有输入的情况下自动设置值,请不要使用
def updateExistingName(name : String) : DBIO[Int] =
{
    map(_.firstName).update(name)
}

def updateOptionName(nameCanBeNone: Option[String]) : DBIO[Int] =
{
    map(_.firstName.?).update(nameCanBeNone)
}