2016-09-01 11 views
0

型推論の問題のために、私のケースクラスとデータベーステーブルの間にカスタム定義されたマッピングを得るのが苦労しています。これは私が元のユースケースからわずか極めてトリムダウンバージョンである、取得していますが、問題を説明するのに十分でなければならないものの例である:Slick 3とのカスタムテーブルマッピング型推論

ここ
case class Example(id: Int, aString: String, optional: Option[Int], extra: String) 

class Examples(tag: Tag) extends Table[Example](tag, "EXAMPLE") { 
    def id = column[Int]("ID", O.AutoInc, O.PrimaryKey) 
    def aString = column[String]("A_STRING") 
    def optional = column[Option[Int]]("AN_OPTIONAL") 

    override def * = (id, aString, optional) <> (constructExample, extractExample) 

    private def constructExample(id: Int, aString: String, optional: Option[Int]): Example = { 
    Example(id, aString, optional, "MY EXTRA DATA") 
    } 

    private def extractExample(e: Example): Option[(Int, String, Option[Int])] = { 
    Some((e.id, e.aString, e.optional)) 
    } 
} 

私は2つのカスタム関数を定義しています私のケースクラスとデータベース行との間の変換に対処する。問題は<>方法は次のエラーを与えて、構築するためのタプルの種類を推測することはできないということである:Slick docs

Error:(60, 50) type mismatch; found : (Int, String, Option[Int]) => SlickExampleRepository.this.Example required: ? => ? override def * = (id, aString, optional) <> (constructExample, extractExample)

次を見つけることができます。

it can also be used with arbitrary mapping functions. In these cases it can be useful to call .shaped on a tuple on the left-hand side in order to get its type inferred properly. Otherwise you may have to add full type annotations to the mapping functions.

には例がありません私は先に進み、次のように試しました:

override def * = (id, aString, optional).shaped <> (constructExample, extractExample) 

これは部分的にしか問題を解決していないようですが、次のエラーが表示されます。

Error:(60, 57) type mismatch; found : (Int, String, Option[Int]) => SlickExampleRepository.this.Example required: ((Int, String, Option[Int])) => ? override def * = (id, aString, optional).shaped <> (constructExample, extractExample)

ので、最終的な仕事は、周りの私は、これはタプルを受け取り、例のオブジェクトを返すようにconstructExample関数のシグネチャを変更することだったため、見つかったので、のように:

private def constructExample(tuple: (Int, String, Option[Int])): Example = { 
    Example(tuple._1, tuple._2, tuple._3, "MY EXTRA DATA") 
} 

しかし、これはかなりあります恐ろしく、エラーが発生しやすくなります。かなり長いタプルを定義し、._1などを使用してその要素にアクセスしていることを考えると、これをどのようにしてniceの方法で動作させるかについてのヒント?

感謝

+0

他のパラメータから 'extra'フィールドを推測できますか?本当にカスタムマッピングが必要なのですか? def * =(id、aString、optional)<>(Example.tupled、Example.unapply) – fGo

+0

長い質問とあなたの提案を読んでいただきありがとうございます。事実、私はこの問題を短い例で説明するためにそのフィールドを追加していますが、実際の使用例は、メインケースクラスを構成する内部オブジェクトを構築する複数の正規化されていないデータベースフィールドです。たとえば、ある期間を生成する2つの日付。 – hasumedic

答えて

0

あなたの*投影を定義するには、次の方法を使用する必要があります。

override def * = (id, aString, optional) <> ((constructExample _).tupled, extractExample) 

constructExample _は、関数にあなたのプライベートメソッドを変換し、.tupledはに3つの引数を使用して機能を変換します1つのTuple3引数を持つ関数。