2014-10-02 6 views
9

मुझे एक हाइबरनेट इकाई के साथ समस्या हो रही है जो प्रारंभ नहीं होता है।
ऐसा लगता है कि यह अभी भी प्रारंभिक प्रॉक्सी नहीं लौटा रहा है ...हाइबरनेट एंटिटी प्रॉक्सी प्रारंभिकरण

यदि मैं अपनी डीबग जानकारी देखता हूं तो मैं अपनी इकाई को आरंभ करने की अपेक्षा करता हूं।
लेकिन यह की तरह लग रहा है:

entity = {[email protected]}"[email protected][id=1,version=0]" 
    handler = {[email protected]} 
     interfaces = {java.lang.Class[2]@9197} 
     constructed = true 
     persistentClass = {[email protected]}"class SomeEntityImpl" 
     getIdentifierMethod = null 
     setIdentifierMethod = null 
     overridesEquals = true 
     componentIdType = null 
     replacement = null 
     entityName = {[email protected]}"SomeEntityImpl" 
     id = {[email protected]}"1" 
     target = {[email protected]200}"[email protected][guid=<null>,id=1,version=0]" 
     initialized = true 
     readOnly = true 
     unwrap = false 
     session = {[email protected]}"SessionImpl(PersistenceContext[entityKeys=[EntityKey[EntityReferenceImpl#2], EntityKey[SomeEntityImpl#1], EntityKey[... 
     readOnlyBeforeAttachedToSession = null 
     sessionFactoryUuid = null 
     allowLoadOutsideTransaction = false 

सूचना है कि मेरी हाइबरनेट POJO अभी भी केवल भी एक स्पष्ट initialisation करने के बाद एक handler शामिल ...
मेरी डिबग ध्यान में रखते हुए मैं 'असली' संपत्ति देख सकते हैं जब मैं target नोड का विस्तार करता हूं तो मान (ऊपर प्रदर्शित नहीं)।

मैं क्या कर रहा हूँ:

EntityReferenceImpl entityReference = findEntityReference(session); 
SomeEntity entity = null; 
if (entityReference != null) { 
    // initialize association using a left outer join 
    HibernateUtil.initialize(entityReference.getSomeEntity()); 
    entity = entityReference.getSomeEntity(); 
} 
return entity; 

सूचना HibernateUtil.initialize कॉल!

SomeEntity मानचित्रण:

public class SomeEntityImpl extends AbstractEntity implements SomeEntity { 
    @OneToMany(mappedBy = "someEntity", fetch = FetchType.EAGER, targetEntity = EntityReferenceImpl.class, orphanRemoval = true) 
    @Cascade(CascadeType.ALL) 
    @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) 
    private Set<EntityReference> entityReferences = new HashSet<>(); 

    @Target(EntityName.class) 
    @Embedded 
    private Name name; 

    @Target(EntityAddress.class) 
    @Embedded 
    private Address address; 

    ... 

} 

EntityReferenceImpl मानचित्रण:

public class EntityReferenceImpl extends AbstractEntity implements EntityReference { 

@ManyToOne(optional = true, fetch = FetchType.LAZY, targetEntity = SomeEntityImpl.class) 
@JoinColumn(name = "entity_id") 
private SomeEntity someEntity; 

... 

} 

तो पक्ष प्रभाव क्या है: POJO बाद में अद्यतन गुण मैं अभी भी एक ही संरचना हो रही है के साथ आता है (उल्लेख किया ऊपर) और मैं target नोड के तहत अद्यतन गुण देख सकता हूं।
लेकिन जब मैं session.merge() या session.update() या session.saveOrUpdate() का उपयोग कर इकाई को अद्यतन करने का प्रयास कर रहा हूं, तो हाइबरनेट 'गंदे' गुणों का पता नहीं लगाता है और डेटाबेस को अद्यतन क्वेरी नहीं देता है।


क्या किसी के पास इस अजीब व्यवहार के बारे में कुछ संकेत हैं? मैंने जो कुछ भी किया है, उसके बिना मैंने कोशिश की है लेकिन बिना किसी परिणाम के।
सभी मदद बहुत स्वागत है !!

+0

'हाइबरनेट यूटिल' कक्षा से कौन सा पैकेज आता है? क्या आप 'हाइबरनेट' कक्षा का उपयोग नहीं करते हैं? – walkeros

+0

DID आप इस मुद्दे को हल करते हैं? मुझे एक समान समस्या का सामना करना पड़ रहा है –

उत्तर

1

हाइबरनेट लाज़ी इकाइयों को कॉल को रोकने के लिए प्रॉक्सी का उपयोग करता है। डीबग में आप जो संरचना देखते हैं वह यह है कि प्रॉक्सी कैसा दिखता है।

आपको HibernateUtil.initialize पर कॉल करने की आवश्यकता नहीं है, लेकिन केवल एक ही क्वेरी में रुचि रखने वाली सभी इकाइयों को लोड करने के लिए "जुड़ें जुड़ें" का उपयोग करें।

यदि इकाई वर्तमान सत्र से जुड़ी हुई है, तो dirty checking mechanism स्वचालित रूप से सभी entity state transitions डेटाबेस डीएमएल कथन में अनुवाद करेगा।

Session.update अलग-अलग इकाइयों को फिर से संलग्न करने के लिए है (इकाइयों को बंद कर दिया गया सत्र में लोड किया गया था)।

Session.merge इकाई राज्य को पहले से लोड की गई इकाई पर कॉपी करने के लिए है (जो फ्लाई पर लोड होता है, अगर पहले लोड नहीं होता है)।

जांचें कि क्या आपने लेनदेन सक्षम किए हैं, अन्यथा आप केवल संस्थाओं का चयन कर सकते हैं। जारी/मर्ज और गंदे जांच अपडेट के लिए आपको लेनदेन का उपयोग करना होगा (जावा ईई या स्प्रिंग @Transactional समर्थन का उपयोग करें)।

+1

मैं आपकी टिप्पणियों से सहमत हूं। मैंने पहले से ही एक एचक्यूएल क्वेरी में 'fetch join' का उपयोग किया है, लेकिन मेरा वही प्रभाव पड़ा।यही कारण है कि मैंने बस सुनिश्चित करने के लिए Hibernate.initialize() की कोशिश की। मैं readOnly = झूठी के साथ वसंत लेनदेन एनोटेशन का उपयोग कर रहा हूँ। ऐसा लगता है कि हाइबरनेट गंदे गुणों का पता नहीं लगाता है। समस्या यह है कि प्रॉक्सी ठीक से शुरू नहीं होता है (जैसे आप डीबग व्यू में देख सकते हैं)। हाइबरनेट प्रारंभिक संगठनों की जांच नहीं करता है (एक जबरदस्त ओवरहेड होगा)। प्रश्न अभी भी क्यों है कि इसे ठीक से शुरू नहीं किया गया है। क्या इसे कार्यान्वयन इंटरफेस के साथ कुछ करना चाहिए? – user2054927

+0

मेरे अनुभव में, इकाइयों पर इंटरफेस संघों से बचने के लिए बेहतर है। आप इंटरफेस कर सकते हैं लेकिन सभी संस्थाओं को वास्तविक संस्थाओं पर बना सकते हैं क्योंकि यह वैसे भी वास्तविक संबंधों को मॉडल करता है। –

7

आपकी डीबग विंडो में इकाई की तरह दिखती है ठीक से प्रारंभ की गई।

जब आप कुछ इकाई है कि हाइबरनेट द्वारा प्रॉक्सी किया जा सकता है, इस इकाई ठीक से किया जा रहा है प्रारंभ होने के बाद भी प्रॉक्सी वस्तु अंदर संग्रहित है। initialisation प्रॉक्सी वस्तु के बाद ही गायब नहीं होता ...

public class EntityReferenceImpl extends AbstractEntity implements EntityReference { 

@ManyToOne(fetch = FetchType.LAZY, ...) 
private SomeEntity someEntity; 
... 

अपने उदाहरण में आप EntityReferenceImpl इकाई जो @ManyToOne(LAZY)SomeEntity को इकाई है की है।

जब हाइबरनेट लोड EntityReferenceImpl यह परिणाम फ़ील्ड मान से सभी फ़ील्ड भरता है लेकिन someEntity फ़ील्ड प्रॉक्सी ऑब्जेक्ट पर सेट है।

इस प्रॉक्सी वस्तुओं इस तरह दिखता है:

class SomeEntity_$$_javassist_3 extends SomeEntity implements HibernateProxy { 
    + firstname = NULL; 
    + lastname = NULL; 
    + age = 0; 
    + handler; //of type: JavassistLazyInitializer 

    getFirstname() { 
    handler.invoke(..., Method thisMethod, Method proceed, args); 
    } 
    getLastName() {...} 
} 

आपका SomeEntity वर्ग (उदाहरण के लिए) तरीके getFirstName() आदि है, लेकिन javassist उत्पन्न वर्ग बस अपने SomeEntity प्रदान करता है और c7getFirstName() की तरह कुछ नए बाईटकोड-उत्पन्न तरीकों है आदि

और सबसे महत्वपूर्ण - प्रॉक्सी वर्ग नए क्षेत्र होते हैं: प्रकार JavassistLazyInitializer की handler। यह firstname की तरह अपने खेतों, lastname आदि जब आप इस प्रॉक्सी को प्रारंभ, SomeEntityभरी हुई है है -

JavassistLazyInitializer { 
    + target; //holds SomeEntity object 
    invoke(..., Method thisMethod, Method proceed, args) { 
    if (target == null) { 
     target = initialize(); // calls sessionImpl.immediateLoad 
    } 
    return thisMethod.invoke(target, args); 
    } 
} 

तो जब आप अपने प्रॉक्सी वस्तु पर गौर:

देखते हैं कि कैसे JavassistLazyInitializer लगता है कि चलो लक्ष्य फ़ील्ड में। आपके firstname, lastname प्रॉक्सी ऑब्जेक्ट्स पर फ़ील्ड से पहले शून्य हैं - प्रॉक्सी उनका उपयोग नहीं करती है, लेकिन असली डेटा SomeEntity ऑब्जेक्ट target फ़ील्ड द्वारा आयोजित किया गया है।

इस प्रकार हाइबरनेट में प्रॉक्सी लागू किया जाता है।

आप पूछ सकते हैं - ऐसा समाधान क्यों? इस तरह के डिजाइन polymorphism मुद्दों से आता है। यदि SomeEntity 2 उपवर्गों EntityA और EntityB हाइबरनेट साथ सार माता पिता वर्ग होगा कोई समस्या नहीं है - someEntity क्षेत्र प्रॉक्सी (उत्पन्न) वर्ग SomeEntity विस्तार लेकिन ठोस EntityA या EntityBtarget क्षेत्र के अंदर होने रखती है।

हालांकि इस समाधान और बहुरूपता के साथ कुछ नुकसान हैं। आपका someEntity फ़ील्ड instance of SomeEntity होगा लेकिन कभीinstance of EntityA और न ही instance of EntityB होगा।

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