2013-03-26 14 views
9

में साथी ऑब्जेक्ट के साथ मैप किए गए प्रोजेक्शन में मैंने कक्षाएं/ऑब्जेक्ट्स निहित किए हैं और 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 
    } 
} 

लेकिन संकलन कई त्रुटियों के साथ विफल रहता है: अतिभारित परिभाषा को अस्पष्ट संदर्भ "विधि unapply दो बार परिभाषित किया गया है", ", दोनों विधि लागू [...] अपेक्षित प्रकार से मिलान करें? " और "अतिभारित विधि मूल्य <> विकल्प के साथ"

मैं मैप किया प्रक्षेपण के "scala slick method I can not understand so far" इस उत्कृष्ट विवरण और "Mapped projection with <> to a case class with companion object in Slick" पाया, लेकिन सुझाव दिया समाधान में से कोई भी मेरे लिए काम।

उत्तर

19
unapply के बजाय

और apply, तो आप सिर्फ lambdas है कि क्या आप चाहते हैं प्रेषित कर सकता है:

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

इस तरह, तालिका पंक्तियों से मानचित्रण कक्षाएं केस करने के लिए तालिका परिभाषा में रहता है, और इस मामले कक्षाएं साधारण केस कक्षाओं के रूप में रहें, जो बहुत बुरा नहीं है।

अन्य तरीके से Foo के लिए एक केस वर्ग का उपयोग नहीं करने के लिए हो गया होता, लेकिन एक नियमित रूप से वर्ग के बजाय जो तुम इतनी तरह अपने खुद के apply और एक साथी वस्तु में unapply परिभाषित करने के लिए नि: शुल्क, छोड़ देता है:

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

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

करना चाहते हैं तो आप एक हद तक मामला श्रेणी की तरह उपयोग मिल जाएगा, लेकिन आप वास्तविक मामले वर्गों के साथ के रूप में मुक्त करने के लिए equals और toString होने की तरह अन्य अच्छा सामान छूट सकते हैं। मैं केस क्लास (और उनके डिफ़ॉल्ट applyunapply) को रखना चाहूंगा ताकि उन्हें सामान्य सम्मेलन में बीजगणितीय डेटा प्रकार के रूप में माना जा सके।

असली मुद्दा यह है कि केस क्लास का अपना unapply है ताकि आप (जहां तक ​​मुझे पता है) आपके साथी वर्ग में एक समान विधि (समान नाम और समान तर्क) न हो। आप बस एक और विधि नाम का उपयोग कर सकते हैं।

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

धन्यवाद एक बहुत सब के बाद, आप क्या करना चाहते हैं नहीं शब्दार्थ बराबर unapply वैसे भी है। वास्तव में मैं आपका पहला समाधान पसंद करता हूं जो बहुत अच्छी तरह से काम करता है। लेकिन लगभग एक दर्जन पैरामीटर के साथ पूरे मैपिंग बॉयलरप्लेट के बहुत सारे प्रतीत होता है। मैं समझता हूं कि स्लिम का डायरेक्ट एम्बेडिंग अधिक कॉम्पैक्ट होगा लेकिन अभी तक सम्मिलन की अनुमति नहीं देता है। मैं यह देखने के लिए उत्सुक हूं कि इस संबंध में स्लिम कैसे प्रगति करेगा। – jans

+1

भले ही आप अपने प्रश्न में 'लागू' और 'अनुपयोगी' तरीके से वर्णन कर सकें, फिर भी आपको अपने दर्जनों पैरामीटर से निपटना होगा? एफडब्ल्यूआईडब्ल्यू, मेरे आखिरी संपादन को देखो। – Faiz

+1

केस क्लास और आपके अंतिम संपादन के साथ मुझे विधि 'लागू' के लिए "अधिभारित परिभाषा के अस्पष्ट संदर्भ" त्रुटि मिलती है। इसलिए, मुझे साथी से ऑब्जेक्ट में 'सेरो' में विधि का नाम बदलना पड़ा। – jans

संबंधित मुद्दे