左连接后发现意外的Nullable

时间:2014-02-05 15:45:15

标签: mysql scala playframework-2.0

我在使用Play开发Web应用程序时遇到了一些麻烦!框架,Scala和Anorm与Mysql。

我有两个案例类:

case class Supplier(id : Pk[Long]= NotAssigned,
         identityId : Option[SupplierIdentity], 
         addressId : Option[Address], userId : User) {}

object Supplier {
      val simple = {
        get[Pk[Long]]("Supplier.id") ~
        SupplierIdentity.simple ~
        Address.simple ~
        User.simple map {
          case id ~ identityId ~ addressId~ userId => 
               Supplier(id, Some(identityId), Some(addressId), userId)
        }

case class Address(id : Pk[Long] = NotAssigned, via : String, cap : Int, comune : String, provincia : String, paese : String) {

}

object Address {

    val simple = {
            get[Pk[Long]]("Address.id") ~
            get[String]("Address.via") ~
            get[Int]("Address.cap") ~
            get[String]("Address.comune") ~
            get[String]("Address.provincia") ~
            get[String]("Address.paese") map {
            case id ~ via ~ cap ~ comune ~ provincia ~ paese=> 
            Address(id, via ,cap , comune , provincia , paese)
            }
    }

在尝试检索供应商时,我有这个查询来访问我的数据库:

def findByIdentity(identityId: Long) : Option[Supplier]= {
      DB.withConnection {implicit connetion =>
      SQL("""SELECT * 
          FROM Supplier 
          LEFT JOIN SupplierIdentity 
          ON Supplier.identity_id= SupplierIdentity.id  
          LEFT OUTER JOIN Address
          ON Supplier.address_id= Address.id   
          LEFT JOIN User 
          ON Supplier.user_id= User.id 
          WHERE Supplier.identity_id={id}""").on('id->identityId).as(Supplier.simple.singleOpt)
    }
   }

我确信它有效,因为我尝试使用Mysql服务器并使用正确的值:

id | identity_id | address_id | user_id | id   | supplier_code | type | ragione_sociale | partita_iva | is_production | id   | via  | cap  | comune | provincia | paese | id   | name    |
+----+-------------+------------+---------+------+---------------+------+-----------------+-------------+---------------+------+------+------+--------+-----------+-------+------+---------+
|  2 |           2 |       NULL |       1 |    2 |             1 | q    | q               |           1 |             1 | NULL | NULL | NULL | NULL   | NULL      | NULL  |    1 | Tiziano |

但是当我尝试从我的控制器使用此方法时,我收到此错误:

  

[RuntimeException的:   UnexpectedNullableFound(的ColumnName(Address.id,有些(ID)))]

这是我的问题,因为那些列可能为null,但我找不到处理null值的方法。我希望wuery能够工作,即使它的某些列是空的。 你能给我一些建议吗?

1 个答案:

答案 0 :(得分:2)

由于您正在使用左连接,因此解析器应该是可选的,如下所示:

case class Supplier(id : Pk[Long]= NotAssigned,
     identityId : Option[SupplierIdentity], 
     addressId : Option[Address], userId : User) {}

object Supplier {
  val simple = {
    get[Pk[Long]]("Supplier.id") ~
    (SupplierIdentity.simple ?) ~
    (Address.simple ?) ~
    (User.simple ?) map {
      case id ~ identityId ~ addressId~ userId => 
           Supplier(id, identityId, addressId, userId)
}

似乎userId也应该是Option[User],因为你还没有加入。如果它不是可选的,它应该是一个内连接(使用原始解析器),否则你会得到同样的问题。发生这种情况的原因是左连接保留所有那些空列,但您的解析器正在查找非空值。 Address.simple ?将解析为Option[Address],当None无法找到整个模型时,会{{1}}。