SLICK

2013-03-26 22 views
9

'da eşlik eden nesne ile eşlenen projeksiyon Yuvalanmış sınıflar/nesneler var ve bunları SLICK kullanarak bir veritabanında saklamak (ve almak) istiyorum. SLICK haritalı projeksiyonun anahtar olacağını anlıyorum. Ayrıca iç içe geçmiş nesneler ve düz yapı (DB tablosunda saklanacak) arasında eşlemek için bir eşlik eden nesne kullanıyorum. Bu (basitleştirilmiş örnekte) gibi bir şey yapmak istiyorum:SLICK

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 
    } 
} 

Ama derleme birkaç hatayla başarısız: "yöntemi uygulamasını kaldırma iki kez tanımlanır", "aşırı tanımına belirsiz başvuru, hem yöntem uygulamak [...] beklenen beklenen maç? " ve

"alternatifleri ile aşırı yöntem değeri <>" Ben bu mükemmel "scala slick method I can not understand so far" eşleştirilmiş projeksiyon açıklama ve "Mapped projection with <> to a case class with companion object in Slick" buldum ama önerilen çözümlerin hiçbiri benim için çalışıyor.

cevap

19
yerine unapply ait

ve apply, sadece ne istiyorsun lambdas içinde geçebileceği:

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 */) 

Bu şekilde, sınıfları harf için tablo satırları gelen eşleştirme tablosu tanımında kalır ve vaka sınıfları Çok kötü olmayan basit vaka sınıfları olarak kalın.

başka yolu Foo için bir vaka sınıfını kullanmayın olurdu, ancak düzenli bir sınıf yerine özgür şöyle bir arkadaşı nesne kendi apply ve unapply tanımlamak bırakır:

// 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)) 
} 

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

yapmak istiyorsanız bir dereceye kadar vaka sınıf benzeri kullanımını alırsınız, ancak gerçek vaka sınıflarıyla olarak ücretsiz equals ve toString olması gibi diğer güzel şeyler kaçırabilirsiniz. Örnek sınıflarını (ve onların varsayılan applyunapply) tutmayı tercih ederim, böylece normal sözleşmede cebirsel veri türleri olarak ele alınabilirler.

Burada asıl konu, vaka sınıflarının kendi unapply'a sahip olmalarıdır, böylece (bildiğim kadarıyla) arkadaş sınıfınızda benzer bir yönteme (aynı ad ve aynı argümanlara) sahip olamazsınız. Başka bir yöntem adı kullanabilirsiniz. tablo şemada Sonra

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 _) 
+1

Çok teşekkürler Sonuçta, ne yapmak istemiyor anlama sahip zaten unapply etmektir. Gerçekten çok iyi çalışan ilk çözümünüzü tercih ederim. Ancak yaklaşık bir düzine parametre ile tüm haritalama pek çok boilerplate gibi görünüyor. SLICK'in Doğrudan Gömme işleminin daha kompakt olacağını ancak henüz eklemeye izin vermediğini anlıyorum. SLICK'in bu açıdan nasıl ilerleyeceğini görmek için sabırsızlanıyorum. – jans

+1

"Uygula" ve "unapply" öğelerini sorgunuzda açıklayabilseniz bile, yine de düzinelerce parametrenizle başa çıkmak zorunda kalacaksınız demektir? FWIW, son düzenlememe bak. – Faiz

+1

Bir vaka sınıfı ve son düzenlemenizde, "başvuru" yöntemi için "aşırı yüklenme tanımına belirsiz bir başvuru" hatası alıyorum. Bu nedenle, eşlik eden nesnede yöntemi 'fromRow' olarak yeniden adlandırmak zorunda kaldım. – jans