2010-09-09 7 views
9

के लिए एसक्यूएल डीएसएल मैं स्कैला के लिए एसक्यूएल डीएसएल बनाने के लिए संघर्ष कर रहा हूं। डीएसएल Querydsl का विस्तार है, जो जावा के लिए एक लोकप्रिय क्वेरी एब्स्ट्रक्शन लेयर है।स्कैला

मैं निम्नलिखित

user.firstName == "Bob" || user.firstName == "Ann" 

की तरह वास्तव में सरल भाव के साथ अब संघर्ष कर रहा हूँ Querydsl पहले से ही एक अभिव्यक्ति मॉडल है जो यहां इस्तेमाल किया जा सकता मैं रूपांतरण प्रदान करने की प्रॉक्सी भाव Querydsl को वस्तुओं से निर्णय लिया का समर्थन करता है के रूप में। आदेश प्रोक्सी का उपयोग करने के लिए मैं इस

import com.mysema.query.alias.Alias._ 

var user = alias(classOf[User]) 
निम्नलिखित निहित रूपांतरण मैं Querydsl में प्रॉक्सी उदाहरणों और प्रॉक्सी संपत्ति कॉल जंजीरों में बदल सकते हैं के साथ

की तरह एक उदाहरण भाव

import com.mysema.query.alias.Alias._ 
import com.mysema.query.types.expr._ 
import com.mysema.query.types.path._ 

object Conversions {   
    def not(b: EBoolean): EBoolean = b.not()   
    implicit def booleanPath(b: Boolean): PBoolean = $(b);   
    implicit def stringPath(s: String): PString = $(s);   
    implicit def datePath(d: java.sql.Date): PDate[java.sql.Date] = $(d);   
    implicit def dateTimePath(d: java.util.Date): PDateTime[java.util.Date] = $(d);   
    implicit def timePath(t: java.sql.Time): PTime[java.sql.Time] = $(t);    
    implicit def comparablePath(c: Comparable[_]): PComparable[_] = $(c);   
    implicit def simplePath(s: Object): PSimple[_] = $(s);   
} 

अब मैं जैसे भाव का निर्माण कर सकते बनाने यह

import com.mysema.query.alias.Alias._ 
import com.mysema.query.scala.Conversions._ 

var user = alias(classOf[User]) 
var predicate = (user.firstName like "Bob") or (user.firstName like "Ann") 

मैं निम्नलिखित समस्या से जूझ रहा हूं।

eq और ne स्काला में तरीकों के रूप में पहले से ही उपलब्ध हैं, इसलिए रूपांतरण शुरू हो रहा नहीं कर रहे हैं, जब वे उपयोग किया जाता है

यह समस्या निम्नलिखित के रूप में सामान्यीकृत किया जा सकता। टाइप नामों का उपयोग करते समय जो पहले से ही स्केल प्रकारों जैसे ईक, ने, स्टार्ट के साथ उपलब्ध हैं, इत्यादि को किसी भी प्रकार के भागने के लिए अंतर्निहित रूपांतरणों को ट्रिगर करने की आवश्यकता होती है।

मैं निम्नलिखित

अपरकेस

var predicate = (user.firstName LIKE "Bob") OR (user.firstName LIKE "Ann") 

यह उदाहरण के लिए Circumflex ORM में दृष्टिकोण, स्काला के लिए एक बहुत शक्तिशाली ORM ढांचे समान डीएसएल के साथ करना है पर विचार कर रहा हूँ। लेकिन यह दृष्टिकोण प्रश्न कीवर्ड (चयन, से, जहां आदि) के साथ असंगत होगा, जो Querydsl में लोअरकेस हैं।

कुछ उपसर्ग

var predicate = (user.firstName :like "Bob") :or (user.firstName :like "Ann") 

विधेय उपयोग के संदर्भ इस

var user = alias(classOf[User]) 

query().from(user) 
    .where( 
     (user.firstName like "Bob") or (user.firstName like "Ann")) 
    .orderBy(user.firstName asc) 
    .list(user); 

की तरह कुछ आपको बेहतर विकल्प या स्काला के लिए एसक्यूएल डीएसएल निर्माण के लिए एक अलग दृष्टिकोण दिखाई दे रही है है?

तो सवाल यह मूल रूप से दो मामलों

  • जब एक विधि है कि सुपर वर्ग में मौजूद है (उदाहरण के लिए eq)

  • यह तो का उपयोग कर एक अंतर्निहित रूपांतरण गति प्रदान करने के क्या यह संभव है करने के लिए नीचे फोड़े संभव नहीं है, eq, ne जैसी विधियों के लिए उपयोग करने के लिए सबसे अधिक स्केलेस्क सिंटैक्स क्या होगा।

संपादित

हम Querydsl में स्काला का समर्थन मिला उर्फ ​​उदाहरणों और एक $ -prefix आधारित भागने सिंटेक्स के उपयोग से काम कर रहे। परिणाम पर एक ब्लॉग पोस्ट यहां दिया गया है: http://blog.mysema.com/2010/09/querying-with-scala.html

+1

तो प्रश्न मूल रूप से दो मामलों तक उबाल जाता है ए) क्या सुपर क्लास (उदाहरण के लिए 'eq') में मौजूद विधि का उपयोग करते समय एक अंतर्निहित प्रकार रूपांतरण को ट्रिगर करना संभव है और बी) यदि यह संभव नहीं है, तो क्या होगा 'eq',' ne' जैसी विधियों के लिए उपयोग करने के लिए सबसे अधिक स्केलेस्क सिंटैक्स बनें। क्या मैं सही ढंग से समझ गया? – ponzao

+0

@ponzao आप मेरे दिमाग को पढ़ रहे हैं! मैंने अपने प्रश्न को "उबला हुआ" एक के साथ समाप्त करने की स्वतंत्रता ली। –

+0

यदि आप इसे स्वयं के लिए नहीं बना रहे हैं, तो ScalaQuery, Scala के लिए एक प्रकार-सुरक्षित डेटाबेस क्वेरी API देखें: http://github.com/szeiger/scala-query –

उत्तर

3

स्कैला दिनों में एक बहुत अच्छी बात थी: टाइप-सुरक्षित एसक्यूएल क्रिस्टोफ वुल्फ द्वारा स्कैला में एम्बेडेड। Type-safe SQL embedded in Scala by Christoph Wulf

+1

सूचक के लिए धन्यवाद। अगर मैं वीडियो को सही ढंग से समझता हूं तो SQL एकीकरण स्रोत प्री-पार्सिंग पर आधारित होता है। मैं बिना किसी प्रीपेरिंग के एक दृष्टिकोण की तलाश कर रहा हूं। –

+0

यह वास्तव में दिलचस्प लग रहा है, यह सुनिश्चित नहीं है कि कार्यान्वयन कैसे चल रहा है। – zinking

1

क्या रनटाइम पर बाईटकोड decompiling के बारे में:

वीडियो यहाँ देखें?

http://h2database.com/html/jaqu.html#natural_syntax

मैं जानता हूँ कि यह एक हैक है, तो कृपया वोट नहीं दें -1 :-) मैं बस चाहता था यह उल्लेख किया: मैं इस तरह के एक उपकरण लिखने के लिए शुरू कर दिया। यह अपेक्षाकृत उपन्यास दृष्टिकोण है। रनटाइम पर डिकंपलिंग करने के बजाय, एनोटेशन प्रोसेसर का उपयोग करके संकलन समय पर ऐसा करना संभव हो सकता है, यह सुनिश्चित नहीं है कि स्कैला का उपयोग करना संभव है (और यह सुनिश्चित नहीं है कि यह जावा के साथ वास्तव में संभव है, लेकिन Project Lombok ऐसा कुछ ऐसा लगता है)।

+0

मैं एक हैक नहीं करता हूं और मूल ऑपरेटरों का उपयोग करने में सक्षम बनाता है, लेकिन मुझे लगता है कि यह अधिक कठिन है और अपघटन के परिणाम प्रयुक्त कंपाइलर पर निर्भर हो सकते हैं। –

3

श्री वेस्टकैम्पर - मैं इस समस्या पर विचार कर रहा था, और मुझे आश्चर्य हुआ कि 'ट्रेसर' ऑब्जेक्ट्स का उपयोग करना संभव होगा, जहां इंट और स्ट्रिंग जैसे मूल डेटा प्रकारों को बढ़ाया जाएगा ताकि उनमें स्रोत जानकारी हो और परिणाम उनके संयोजन के साथ ही उनके स्रोतों और संयोजन की प्रकृति के भीतर ही होगा।

उदाहरण के लिए, आपका उपयोगकर्ता। फर्स्टनाम विधि एक ट्रैसरस्ट्रिंग लौटाएगी, जो स्ट्रिंग को बढ़ाती है, लेकिन यह भी इंगित करती है कि स्ट्रिंग एक संबंध में कॉलम से मेल खाती है। == विधि को ओवरराइट किया जाएगा जैसे कि यह एक समानता ट्राउज़रबोलियन देता है जो बूलियन को बढ़ाता है। यह मानक स्कैला अर्थशास्त्र को संरक्षित करेगा। हालांकि, EqualityTracerBoolean के लिए निर्माता इस तथ्य को रिकॉर्ड करेंगे कि अभिव्यक्ति का परिणाम एक स्ट्रिंग स्थिरता के संबंध में कॉलम की तुलना करके लिया गया था। आपके 'कहां' विधि का निर्माण करने के लिए उपयोग की जाने वाली अभिव्यक्ति प्राप्त करने के लिए एक डमी तर्क पर मूल्यांकन की गई सशर्त अभिव्यक्ति द्वारा लौटाई गई समानता ट्रैसरबोलियन ऑब्जेक्ट का विश्लेषण किया जा सकता है।

असंतुलित ऑपरेटरों के साथ-साथ प्लस और माइनस, इन्ट्स के लिए, और जो कुछ भी आप एसक्यूएल से प्रतिनिधित्व करना चाहते थे, और इनमें से प्रत्येक के लिए संबंधित ट्रैसर कक्षाओं के लिए डीफ़ ओवरराइड करना होगा। यह एक परियोजना का थोड़ा सा होगा!

वैसे भी, मैंने परेशान न करने का फैसला किया, और इसके बजाय squeryl का उपयोग किया। equal, notEqual, आदि के बजाय eq, ne:

+0

आपके विस्तृत उत्तर के लिए धन्यवाद। मेरा मानना ​​है कि थॉमस म्यूएलर ने एच 2/जाक्वा में ऐसा कुछ किया है। मुझे यकीन नहीं है कि स्केल में बूलियन इत्यादि बढ़ाया जा सकता है या नहीं। यह एक दिलचस्प दृष्टिकोण है, लेकिन वास्तव में श्रमिक है। –

2

मैं के रूप में मैं थोड़ा और वर्बोज़ ऑपरेटर नाम उपयोग कर रहा हूँ, jOOQ साथ ठीक उसी समस्या नहीं थी। दूसरी तरफ, jOOQ में val ऑपरेटर स्पष्ट रूप से बाध्य मान बनाने के लिए है, जिसे मुझे value के साथ ओवरलोड करना था, क्योंकि val स्कैला में एक कीवर्ड है। ऑपरेटरों को ओवरलोडिंग आपके लिए एक विकल्प है?

http://lukaseder.wordpress.com/2011/12/11/the-ultimate-sql-dsl-jooq-in-scala/

बस आप की तरह

, मैं भी (SELECT, FROM, आदि सहित) एक प्रमुख रिहाई के सभी कीवर्ड को बड़े अक्षरों में के बारे में सोचा था: मैं यहाँ स्काला में jOOQ चलाने का मेरा प्रयास प्रलेखित। लेकिन यह एक खुला प्रश्न छोड़ देगा कि "कंपाउंड" कीवर्ड को दो विधि कॉल में विभाजित किया जाना चाहिए, या अंडरस्कोर से जोड़ा जाना चाहिए: GROUP().BY() या GROUP_BY()WHEN().MATCHED().THEN().UPDATE() या WHEN_MATCHED_THEN_UPDATE()। चूंकि परिणाम वास्तव में संतोषजनक नहीं है, मुझे लगता है कि इस तरह के एक फिक्स के लिए पिछड़ा-संगतता तोड़ना उचित नहीं है, भले ही दो-विधि-कॉल विकल्प स्कैला में बहुत अच्छा लगेगा, . और () को छोड़ा जा सकता है। तो हो सकता है कि, jOOQ और QueryDSL दोनों को एक समर्पित स्कैला-एपीआई द्वारा "लपेटा" ("विस्तारित" के विपरीत) होना चाहिए?