복붙노트

[SCALA] 슬릭의 동반자 객체와 매핑 프로젝션

SCALA

슬릭의 동반자 객체와 매핑 프로젝션

나는 상자의 클래스 / 객체를 저장하려는 (및 검색) 슬릭를 사용하여 데이터베이스에 있습니다. 나는 SLICK 매핑 돌기가 열쇠가 될 것이라는 점을 잘 알고 있습니다. 또한 I 중첩 물체 평면 구조합니다 (DB 테이블에 저장되는) 맵하는 컴패니언 오브젝트를 사용한다. 나는이 (간체 예) 같은 것을하고 싶지 :

case class Foo(id: Int, myBar: Bar)

case class Bar(myInt: Int, myString: String)

object Foo {
  def apply(id: Int, myInt: Int, myString: String): Foo = Foo(id, Bar(myInt, myString))

  override def unapply(f: Foo) = (f.id, f.myBar.myInt, f.myBar.myString)
}

object TTable extends Table[Foo]("FOO") {
    def id = column[Int]("id",  O.PrimaryKey)
    def myInt = column[Int]("myInt", O NotNull)
    def myString = column[String]("myString", O NotNull)

    def * = id ~ myInt ~ myString <> (Foo.apply _, Foo.unapply _)

    def query(db: Database, id: Int): Option[Foo] = db withSession { //s: Session =>
        (for { b <- TTable if b.id is id} yield b).firstOption
    }
}

그러나 컴파일이 몇 가지 오류와 함께 실패합니다 : "방법을 적용 취소 두 번 정의", "오버로드 정의에 대한 모호한 참조, 두 방법은 [...] 예상 유형과 일치 적용?" 및 "오버로드 된 메소드 값 <> 대안"

나는 나를 위해 제안 된 솔루션을 작업하지만 없음 "동반자 슬릭의 객체 경우 클래스에 <>로 매핑 된 투사"이 매핑 된 투사의 훌륭한 설명 "스칼라 매끄러운 방법 지금까지 이해할 수 없다"를 발견했다.

해결법

  1. ==============================

    1.대신 적용 취소 및 적용, 당신은 당신이 원하는 것을 할 람다에 전달할 수 :

    대신 적용 취소 및 적용, 당신은 당신이 원하는 것을 할 람다에 전달할 수 :

      def * = id ~ myInt ~ myString <> (
        (id,myInt,myString) => Foo(id, Bar(myInt, myString)),    /* from a row to a Foo */
        (f:Foo) => Some((f.id, f.myBar.myInt, f.myBar.myString)) /* and back */)
    

    이 방법, 테이블 정의의 경우 클래스 숙박, 케이스 클래스와 테이블 행의 매핑은 나쁘지 않네요 간단한 경우 클래스로 유지됩니다.

    다른 방법은 푸의 경우 클래스를 사용하지 않도록했을 것이다, 그러나 당신이 당신의 자신을 정의하기 위해 무료 잎 대신 일반 클래스과 같이, 동반자 개체에 적용 취소 적용 :

    // untested code
    class Foo private (val id: Int, val myBar: Bar) 
    case class Bar(myInt: Int, myString: String)
    object Foo {
      def apply(id: Int, myInt: Int, myString: String): Foo = new Foo(id, Bar(myInt, myString))
      def unapply(f: Foo) = Some((f.id, f.myBar.myInt, f.myBar.myString))
    }
    

    당신이 데프하고 싶은 경우 * = ID ~ 민트 ~ mystring에 <> (Foo.apply _, Foo.unapply _)

    당신은 정도 사용 케이스 클래스와 같은거야,하지만 당신은 다른 좋은 물건을 놓칠 수 실제 케이스 클래스와 마찬가지로 무료 등호 및 toString을 가지고있다. 그들은 정상적인 대회에서 대수 데이터 유형으로 처리 할 수 ​​있도록 차라리 경우 클래스를 유지하는 것 (및 기본 적용 취소시).

    여기 진짜 문제는이 경우 클래스는 당신이하지 (내가 아는 한) 컴패니언 클래스에서 비슷한 방식 (같은 이름과 같은 인수)을 가질 수 적용 취소 그래서 자신을 가지고 있습니다. 당신은 단순히 또 다른 방법 이름을 사용할 수 있습니다. 결국, 당신이하고 싶은 것은 아니다 적용 취소 어쨌든 의미 적으로 동등 :

    object Foo {
      def fromRow(id: Int, myInt: Int, myString: String): Foo = Foo(id, Bar(myInt, myString))
      def toRow(f: Foo) = Some((f.id, f.myBar.myInt, f.myBar.myString))
    }
    

    그런 다음 테이블 스키마에서 :

    def * = id ~ myInt ~ myString <> (Foo.fromRow _, Foo.toRow _)
    
  2. from https://stackoverflow.com/questions/15627981/mapped-projection-with-companion-object-in-slick by cc-by-sa and MIT license