5

से मेल नहीं खाता मैं spring-data-mongodb संस्करण 1.1.1.RELEASE के साथ निम्न वस्तु लागू करने के लिए कोशिश कर रहा हूँ:PersistenceConstructor तर्क चर नाम उदाहरण चर नाम

@Document 
public static class TestObject { 

    private final int m_property; 

    @PersistenceConstructor 
    public TestObject(int a_property) { 
     m_property = a_property; 
    } 

    public int property() { 
     return m_property; 
    } 

} 

मैं एक MappingException जब मैं वस्तु डेटाबेस से वापस पढ़ने की कोशिश (नीचे पूर्ण स्टैकट्रैक देखें)

नामकरण सम्मेलन मेरे समूह के उपयोग के लिए a_ द्वारा पूर्ववर्ती तर्क चर नामों की आवश्यकता होती है और उदाहरण चर नाम m_ द्वारा पूर्ववर्ती किए जाने चाहिए। ऐसा लगता है कि spring-data-mongodb यह धारणा बना रहा है कि कन्स्ट्रक्टर तर्क परिवर्तनीय नाम ऑब्जेक्ट इंस्टेंस वेरिएबल नामों से मेल खाना चाहिए।

  • क्यों spring-data-mongodb कन्स्ट्रक्टर के भीतर परिभाषित आवृत्ति मैपिंग के लिए कन्स्ट्रक्टर तर्क का उपयोग नहीं करता है?
  • क्या इस मैपिंग को परिभाषित करने का कोई और तरीका है कि spring-data-mongodb ठीक से मेरी ऑब्जेक्ट का निर्माण करेगा, या नामकरण सम्मेलन तोड़ने का मेरा एकमात्र विकल्प है?

Exception in thread "main" org.springframework.data.mapping.model.MappingException: No property a_property found on entity class com.recorder.TestRecorder$TestObject to bind constructor parameter to! 
    at org.springframework.data.mapping.model.PersistentEntityParameterValueProvider.getParameterValue(PersistentEntityParameterValueProvider.java:90) 
    at org.springframework.data.convert.ReflectionEntityInstantiator.createInstance(ReflectionEntityInstantiator.java:70) 
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:229) 
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:209) 
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:173) 
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:169) 
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:72) 
    at org.springframework.data.mongodb.core.MongoTemplate$ReadDbObjectCallback.doWith(MongoTemplate.java:1820) 
    at org.springframework.data.mongodb.core.MongoTemplate.executeFindMultiInternal(MongoTemplate.java:1542) 
    at org.springframework.data.mongodb.core.MongoTemplate.findAll(MongoTemplate.java:1064) 
    at com.recorder.TestRecorder.main(TestRecorder.java:43) 
+0

यह वास्तव में क्रोधित नामकरण सम्मेलन है जो कोई समझ नहीं लेता है। –

उत्तर

16

tl;। डॉ

हम क्षेत्र नाम से मेल करने पता लगाने के लिए दस्तावेज़ के जो क्षेत्र में खींचने के लिए आप निर्माता तर्क पर इस प्रयोग @Value("#root.field_name") कस्टमाइज़ करना चाहते हैं निर्माता तर्क के नाम पर भरोसा करने की जरूरत है।

लंबी कहानी

आप स्प्रिंग डाटा किसी वर्ग इस निर्माता हम मंगलाचरण पर निर्माता के लिए मानकों को सौंपने के लिए है का उपयोग कर का दृष्टांत जाने के लिए तर्क के साथ एक निर्माता उपयोग कर रहे हैं। यह जानने के लिए कि हमें कौन सा दस्तावेज़ फ़ील्ड सौंपना है, हमें संभावित फ़ील्ड नाम अनुकूलन के लिए मिलान करने वाली संपत्ति का निरीक्षण करना होगा। निम्नलिखित उदाहरण देखें:

@Document 
class MyEntity { 

    @Field("foo") 
    private String myField; 

    public MyEntity(String myField) { 
    this.myField = myField; 
    } 
} 

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

इस व्यवहार को कस्टमाइज़ करने के लिए आप स्प्रिंग के @Value एनोटेशन का उपयोग कर सकते हैं और कन्स्ट्रक्टर में एक कस्टम दस्तावेज़ फ़ील्ड इंजेक्ट कर सकते हैं। दस्तावेज़ स्वयं #root चर के माध्यम से उपलब्ध है। ताकि आप आसानी से करने के लिए ऊपर मेरी नमूना बदल सकता है:

@Document 
class MyEntity { 

    @Field("foo") 
    private String myField; 

    public MyEntity(@Value("#root.foo") String somethingDifferent) { 
    this.myField = somethingDifferent; 
    } 
} 

मैं दृढ़ता से अनुशंसा करते हैं कि आप अपने गुणों के कस्टम फ़ील्ड नाम जोड़ने के साथ-साथ आप डेटाबेस के लिए अपनी संपत्ति नामकरण सम्मेलनों का पर्दाफाश करने के नहीं करना चाहती। reference docs में उपयोग पीएफ @Value का संक्षेप में उल्लेख किया गया है लेकिन मैंने दस्तावेज़ों को बेहतर बनाने और इसे और स्पष्ट करने के लिए a ticket बनाया है।

+0

आपके लिए एक फॉलो-अप प्रश्न - यदि मैं आपके द्वारा सुझाए गए कार्यों को करता हूं, तो ऐसा लगता है कि केवल उन वस्तुओं के लिए काम करना है जिनमें केवल प्राइमेटिव हैं, लेकिन जब भी मैं ऑब्जेक्ट्स का उपयोग करने की कोशिश करता हूं तो मुझे अपवाद मिलता है जिसमें अन्य ऑब्जेक्ट होते हैं। क्या आप जानते हैं कि यहां क्या हो रहा है? मैंने विवरण [प्रश्न 13854753] में सूचीबद्ध किया है (http://stackoverflow.com/questions/13854753) –

+0

एफवाईआई - मैंने [DATAMONGO-592] बनाया है (https://jira.springsource.org/browse/DATAMONGO -592) अन्य वस्तुओं वाले वस्तुओं का उपयोग करने में सक्षम नहीं होने के मुद्दे को ट्रैक करने के लिए। आपकी सहायता के लिए धन्यवाद!! –

+0

ओह कैसे मैं stackoverflow प्यार करता हूँ और जो इसमें योगदान करते हैं! मैं कुछ गलत दिनों का पता लगाने की कोशिश कर रहा था कि क्या गलत है, आपने बस मुझे उस समय और निराशा को बचाया। धन्यवाद! – TheZuck

0

आप कुछ कस्टम कन्वर्टर्स उपयोग कर सकते हैं (और @PersistenceConstructor निकालने के लिए):

// DB => Java 
package com.recorder.converters; 

public class TestObjectReadConverter implements Converter<DBObject, TestObject> 
{ 
    public TestObject convert(final DBObject source) { 
     return new TestObject((Integer) source.get("m_property")); 
    } 
} 

// JAVA => DB 
package com.recorder.converters; 

public class TestObjectWriteConverter implements Converter<TestObject, DBObject> 
{ 
    public DBObject convert(final TestObject source) { 
     return new BasicDBObjectBuilder("m_property", source.property()).get(); 
    } 
} 

मत भूलना उन (xml config) घोषित करने के लिए:

<mongo:mapping-converter base-package="com.recorder"> 
    <mongo:custom-converters> 
     <mongo:converter> 
      <bean class="com.recorder.converters.TestObjectReadConverter" /> 
     </mongo:converter> 
     <mongo:converter> 
      <bean class="com.recorder.converters.TestObjectWriteConverter"/> 
     </mongo:converter> 
    </mongo:custom-converters> 
</mongo:mapping-converter> 

देख this reference

साइड नोट: इस एक काम के आसपास है, मुझे नहीं लगता कि नामकरण परिपाटी इतने तंग होने के लिए हैं कि आपको आसपास काम करने की ज़रूरत है। शायद आपके समूह के लिए उन नामकरण सम्मेलन (उस मामले में उत्पादकता के लिए) पर "पुनर्विचार" करने का समय है।

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