2014-12-10 11 views
6

परीक्षण के लिए एक हाइबरनेट प्रॉक्सी अनुकरण निम्न के समान एक डोमेन वर्ग पदानुक्रम के साथ grails का उपयोग करते समय:Grails:

abstract class Vehicle { ... } 
class Car extends Vehicle { ... } 
class Motorcycle extends Vehicle { ... } 

और निम्नलिखित के रूप में एक सेवा:

class VehicleService { 
    def startRepairing(Car car) { ... } 
    def startRepairing(Motorcycle motorcycle) { ... } 
} 

हम बहुत बार हम सामना निम्नलिखित में त्रुटियों के रूप में त्रुटियां:

विधि का कोई हस्ताक्षर नहीं: VehicleService.startRepairing()के लिए लागू हैतर्क प्रकार: (कार _ $$ _ javassist_156) मूल्य: [आईडी: 42343, कक्षा: कार]। संभावित समाधान: startRepairing (कार)

हमारा मानना ​​है कि ऐसा होता है क्योंकि हम एक संग्रह के रूप में static hasMany = [vehicles: Vehicle] है, जिससे प्रॉक्सी सार वर्ग Vehicle नहीं बल्कि ठोस वर्ग (Car को लागू करने का कारण बनता है से Vehicle उदाहरण पुनः प्राप्त, Motorcycle , आदि)।

हम एक समाधान के रूप में विधि से तर्क प्रकार निकालने के लिए किया है, लेकिन हम नहीं बल्कि यह होता है - कोड क्लीनर है, विधि अधिभार संभव है, और अधिक आईडीई अनुकूल है ...

एक समाधान हमने सोचा के बारे में है कुख्यात GrailsHibernateUtil.unwrapIfProxy उपयोग करने के लिए जब प्रकार किसी भी अन्य विधि से मेल नहीं खाता:

class VehicleService { 
    def startRepairing(Vehicle vehicle) { 
     startRepairing(GrailsHibernateUtil.unwrapIfProxy(vehicle)) 
    } 
    def startRepairing(Car car) { 
     /* actual business logic here */ 
    } 
    def startRepairing(Motorcycle motorcycle) { 
     /* actual business logic here */ 
    } 
} 

लेकिन फिर सवाल, कैसे हम इस परीक्षण कर सकते हैं कर रहा है? विकास में कोड चलाते समय हमें शायद ही कभी जावास्त्री की समस्या मिलती है, और यहां तक ​​कि उत्पादन में भी यह "यादृच्छिक रूप से" होता है (या अधिक सटीक, हमारे ज्ञान से बचने वाली स्थितियों के कारण :)।

क्या एक उदाहरण को जवासिस्ट प्रॉक्सी होने के लिए मजबूर करना संभव है? सामान्य रूप से इस तरह की समस्याओं के लिए एक अच्छी रणनीति क्या होगी?

+0

यो यूकान ग्रोवी के गतिशील पक्ष का उपयोग करें और अपने कोड में कार के बजाय ऑब्जेक्ट घोषित करें। रनटाइम पर, विधि प्रॉक्सी इंस्टेंस पर पाई जाएगी और सभी ठीक होंगे। – MatRt

+0

परीक्षण सीमाओं के कारण मेरी विधि के हस्ताक्षर को बदलना मेरे लिए अच्छा नहीं लगता है: -/ – Deigote

उत्तर

6

हाइबरनेट प्रॉक्सी बनाता है जब आपको आंशिक रूप से लोड होने वाले क्लास इंस्टेंस की आवश्यकता होती है। आपको किसी ऐसी चीज की आवश्यकता है जो अपेक्षित वर्ग का उदाहरण या उप-वर्ग है, और एक बार पूरी तरह से लोड हो जाने पर, यह मूल रूप से उत्सुकतापूर्वक लोड किए गए उदाहरण की तरह कार्य करता है। प्रॉक्सी के रूप में उपयोग करने के लिए अपनी कक्षाओं का एक उप-वर्ग बनाने के लिए बाइटकोड लाइब्रेरी का उपयोग करने के लिए हाइबरनेट का दृष्टिकोण अच्छी तरह से काम करता है।

तो 1-1 के लिए और 1-कई के 'एक' पक्ष के लिए, आलसी लोडेड उदाहरण प्रॉक्सी होगा। आलसी लोड वाले संग्रहों में भी जो "अतिरिक्त आलसी" हैं, उदाहरण सभी प्रॉक्सी होंगे। यह बेहतर काम करता है जब आपको पता होता है कि आपको केवल कुछ संग्रहों से डेटा की आवश्यकता होगी - संग्रह पर "पॉप्युलेट" करने के लिए, जब मांग पर लोड होने की आवश्यकता होती है, तो क्वेरी केवल आईडी की तलाश करती है, और संग्रह में उदाहरण प्रॉक्सी होंगे केवल आईडी संग्रहित के साथ। यदि आप पूरे संग्रह के माध्यम से लूप करते हैं तो आप इसे एन + 1 प्रश्नों को चलाते हैं, लेकिन यदि आपको केवल कुछ की आवश्यकता है, तो आम तौर पर संग्रह के सभी मामलों के लिए सभी डेटा लोड करने से कम संसाधन-गहन होना चाहिए था जनसंख्या, और गैर प्रॉक्सी संग्रह सदस्यों को बनाने अगर केवल कुछ की जरूरत है।

एक अन्य आसान जगह जहां आप प्रॉक्सी देखते हैं load() विधि के साथ है। get() पहले लोड किए गए मानों के लिए पहले और दूसरे (यदि डोमेन क्लास के लिए सक्रिय और सक्षम है) में दिखता है और अन्यथा तुरंत डेटाबेस पर जाता है, तो उस आईडी के लिए कोई रिकॉर्ड नहीं होने पर शून्य को वापस कर दिया जाता है। यह अपवाद नहीं फेंकता है क्योंकि यह जानना आसान है कि यह सफल हुआ है या नहीं। load() हालांकि यदि आप आईडी के अलावा किसी अन्य संपत्ति का उपयोग करते हैं तो केवल डेटाबेस को हिट करता है।यदि कोई रिकॉर्ड नहीं है, तो एक अपवाद दोनों को फेंक दिया जाता है क्योंकि आप आवश्यक नहीं हैं (समय-वार या कोड-वार) शुरुआती load() कॉल जो प्रॉक्सी बनाते हैं, और क्योंकि यह भी एक अनुमान है कि आलसी लोडिंग द्वारा, आप हैं परिणाम की उम्मीद है, इसलिए इस मामले में एक शून्य असाधारण है।

+0

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