Map inheritance in slick 2.0

空扰寡人 提交于 2020-01-24 15:40:26

问题


I know there are other questions in stack overflow, but None of them works for me.

I'm trying to map a simple inheritance in slick projection

I try hundreds of combinations, I can't make this compile. I end of with the follow code and the error bellow.

I simplify the case classes because they have much more data. Without inheritance my other layers (controllers, services and interface) will have to deal with complexity, because in this case the model represents real objects that are in trisect inherited, there is no better representation that inheritance for this classes. In the service and controller layer I make the Json representation of the classes be exacted what I need, I can send and consume a Json API that represents my model, the only thing in the way is persisting this representation in relational database, my relational model is capable of persist this entities in an single table inheritance, but translate rows to relational is a pain.

I'm using scala 2.10.3 + sbt 0.13.1

abstract class Pessoa2(val nome:String, val tipo:String)
case class PessoaFisica2(override val nome:String, val cpf:String) extends Pessoa2(nome,"F")
case class PessoaJuridica2(override val nome:String, val cnpj:String) extends Pessoa2(nome, "J")

class PessoaTable(tag: Tag) extends Table[Pessoa2](tag, "PESSOAS"){
//    def id = column[Int]("ID", O.PrimaryKey, O.AutoInc)
def nome = column[String]("nome")
def tipo = column[String]("tipo")
def cpf = column[String]("CPF", O.Nullable)
def cnpj = column[String]("CNPJ", O.Nullable)

def * = (nome, tipo, cpf.?, cnpj.?) <> ({
      case (nome:String,"F",cpf:Option[String],_) => new PessoaFisica2(nome, cpf.get):Pessoa2
      case (nome:String,"J",_,cnpj:Option[String]) => new PessoaJuridica2(nome, cnpj.get):Pessoa2
    },{
    case PessoaFisica2(nome, Some(cpf)) => Some((nome, "F", cpf, ""))
    case PessoaJuridica2(nome, Some(cnpj)) => Some((nome, "J", "", cnpj))
  })
}

This ends with the error:

The argument types of an anonymous function must be fully known. (SLS 8.5) [error] Expected type was: ? => ?

[error] def * = (nome, tipo, cpf.?, cnpj.?) <> ({

[error] ^

[error] /Users/giovanni/Projetos/atende/clientes/app/model/Pessoas.scala:158: type mismatch;

[error] found : Any

[error] required: String

[error] case (nome,"F",cpf,_) => new PessoaFisica2(nome, cpf):Pessoa2

[error] ^

[error] /Users/giovanni/Projetos/atende/clientes/app/model/Pessoas.scala:158: type mismatch;

[error] found : Any

[error] required: String

[error] case (nome,"F",cpf,_) => new PessoaFisica2(nome, cpf):Pessoa2

[error] ^

[error] /Users/giovanni/Projetos/atende/clientes/app/model/Pessoas.scala:159: type mismatch;

[error] found : Any

[error] required: String

[error] case (nome,"J",_,cnpj) => new PessoaJuridica2(nome, cnpj):Pessoa2

[error] ^

[error] /Users/giovanni/Projetos/atende/clientes/app/model/Pessoas.scala:159: type mismatch;

[error] found : Any

[error] required: String

[error] case (nome,"J",_,cnpj) => new PessoaJuridica2(nome, cnpj):Pessoa2

[error] ^

[error] /Users/giovanni/Projetos/atende/clientes/app/model/Pessoas.scala:160: missing parameter type for expanded function

[error] The argument types of an anonymous function must be fully known. (SLS 8.5)

[error] Expected type was: ? => Option[?]

[error] },{

[error] ^

[error] /Users/giovanni/Projetos/atende/clientes/app/model/Pessoas.scala:157: 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: scala.slick.lifted.ShapeLevel.Flat

[error] Source type: (scala.slick.lifted.Column[String], scala.slick.lifted.Column[String], scala.slick.lifted.Column[Option[String]], scala.slick.lifted.Column[Option[String]])

[error] Unpacked type: (String, String, String, String)

[error] Packed type: Any

[error] def * = (nome, tipo, cpf.?, cnpj.?) <> ({

[error] ^

[error] 7 errors found


回答1:


Try that:

abstract class Pessoa2(val nome:String, val tipo:String)
case class PessoaFisica2(override val nome:String, val cpf:String) extends Pessoa2(nome,"F")
case class PessoaJuridica2(override val nome:String, val cnpj:String) extends Pessoa2(nome, "J")


class PessoaTable(tag: Tag) extends Table[Pessoa2](tag, "PESSOAS"){
//    def id = column[Int]("ID", O.PrimaryKey, O.AutoInc)
def nome = column[String]("nome")
def tipo = column[String]("tipo")
def cpf = column[String]("CPF", O.Nullable)
def cnpj = column[String]("CNPJ", O.Nullable)

def * = (nome, tipo, cpf.?, cnpj.?) <> ({ t : (String, String, Option[String], Option[String])=> t match{
    case (nome:String,"F",cpf:Option[String],_) => new PessoaFisica2(nome, cpf.get):Pessoa2
    case (nome:String,"J",_,cnpj:Option[String]) => new PessoaJuridica2(nome, cnpj.get):Pessoa2
  }},{ k: Pessoa2 => k match{
    case PessoaFisica2(nome, cpf) => Some((nome, "F", Some(cpf), Some(""))): Option[(String, String, Option[String], Option[String])]
    case PessoaJuridica2(nome, cnpj) => Some((nome, "J", Some(""), Some(cnpj))): Option[(String, String, Option[String], Option[String])]
  }})
}

It should compile that way



来源:https://stackoverflow.com/questions/22132871/map-inheritance-in-slick-2-0

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!