2009-06-24 8 views
18

क्या इकाई ऑब्जेक्ट को संपादित किए बिना जेपीए फ़ेच प्रकार को एक ही विधि पर बदलने का कोई तरीका है?क्या किसी विधि पर जेपीए फ़ेच प्रकार बदलने का कोई तरीका है?

मेरे पास एक साझा ओआरएम परत है जिसमें जेपीए इकाई वर्ग शामिल हैं। यह ओआरएम परत दो डीएओ परतों द्वारा उपयोग की जाती है। एक डीएओ को आलसी लाने की ज़रूरत है, क्योंकि यह मेरे वेब एप्लिकेशन के लिए है, अन्य को उत्सुकता की आवश्यकता है, क्योंकि मुझे इसे थ्रेडसेफ होने की आवश्यकता है।

यहाँ मेरी threadsafe डीएओ से एक उदाहरण विधि है,

@PersistenceContext(unitName = "PersistenceUnit", 
type = PersistenceContextType.TRANSACTION) 
private EntityManager em; 

public ErrorCode findErrorCodeById(short id) { 
    return (ErrorCode) em.createNamedQuery("ErrorCode.findById"). 
      setParameter("id", id).getSingleResult(); 
} 

मैं इस विधि (या पूरी क्लास) उत्सुक प्राप्त कर रहा है का उपयोग कैसे होगा?

उत्तर

15

मुझे लगता है तो अपनी इकाई के संघों (@OneToOne, @OneToMany, @ManyToOne) आलसी fechted कर रहे हैं (FetchType.Lazy)

तो मैं दो तरीकों के बारे में सोच सकते हैं कि:

ए दो जेपीए क्वेरी लिखने एक जो आलसी (जो हाइबरनेट के लिए डिफ़ॉल्ट तरीका है) का सहयोग प्राप्त करता है और एक दूसरी क्वेरी जो स्पष्ट बल को एसोसिएशन की लोडिंग को उत्सुक करता है (क्वेरी में "fetch" कीवर्ड देखें)।

 
     Query q = HibernateUtil.getSessionFactory().getCurrentSession() 
       .createQuery("select c from Category as c" + 
         " left join fetch c.categorizedItems as ci" + 
         " join fetch ci.item as i"); 


बी के बाद आप इसे पुनः प्राप्त है Hibernate.initialize (इकाई) एक इकाई के आलसी संबंधों के लिए उत्सुक लोड हो रहा है के लिए मजबूर करने का उपयोग करें (खोजक के माध्यम से जैसे ...)

 
ErrorCode lazyCode = findErrorCodeById(1); 
// eager load associations 
Hibernate.initialize(lazyCode); 
+0

धन्यवाद क्लाउस, स्पष्ट रूप से विकल्प बी कोड हाइबरनेट, जो एक ड्रॉ वापस आ गया है आयात करने पर निर्भर कर रहा है, लेकिन मैं:

आप "loadgraph" और "fetchgraph" यहाँ के बीच अंतर की जानकारी प्राप्त कर सकते यह एक कोशिश दे देंगे। –

+1

हाय निमो, क्या आप कृपया मेरे उत्तर को हरे रंग के चेकमार्क के साथ चिह्नित कर सकते हैं। ;) – H2000

+0

मैं अभी भी विधि बी का उपयोग कर 'सत्र बंद' मुद्दा मार रहा हूं। –

9

जेपीए में लायें मोड प्रत्येक दृढ़ता विशेषता पर, एक एनोटेशन के माध्यम से या एक एक्सएमएल मैपिंग फ़ाइल में निर्दिष्ट किया गया है।

तो आपके लक्ष्य को पूरा करने के लिए एक जेपीए विक्रेता अज्ञेय तरीका प्रत्येक डीएओ परत के लिए अलग मैपिंग फ़ाइल रखना है। दुर्भाग्यवश, प्रत्येक मैपिंग फ़ाइल के लिए इसे एक अलग पर्सिस्टेंस यूनिट की आवश्यकता होगी, लेकिन आप कम से कम एक ही इकाई वर्ग और एक ही जेपीक्यूएल क्वेरी साझा कर सकते हैं।

कोड कंकाल का पालन करें।

persistence.xml:

<persistence> 
    <persistence-unit name="dao-eager"> 
     <mapping-file>orm-eager.xml</mapping-file> 
    </persistence-unit> 

    <persistence-unit name="dao-lazy"> 
     <mapping-file>orm-lazy.xml</mapping-file> 
    </persistence-unit> 
</persistence> 

ORM-eager.xml:

<entity-mappings> 
    <entity class="ErrorCode"> 
     <attributes> 
      <basic name="name" fetch="EAGER"/> 
     </attributes> 
    </entity> 
</entity-mappings> 

ORM-lazy.xml:

<entity-mappings> 
    <entity class="ErrorCode"> 
     <attributes> 
      <basic name="name" fetch="LAZY"/> 
     </attributes> 
    </entity> 
</entity-mappings> 

तो यह एक EntityManagerFactory बनाने का मामला है आपके डीएओ परतों में उपयुक्त दृढ़ता-इकाई के लिए।

असल में आपको दो मैपिंग फ़ाइलों की आवश्यकता नहीं है, तो आप एंटीटी में एनोटेशन के रूप में या तो लाज़ी या ईगर निर्दिष्ट कर सकते हैं और फिर एक एक्सएमएल मैपिंग फ़ाइल में विपरीत निर्दिष्ट कर सकते हैं (हालांकि आप अभी भी दो दृढ़ता-इकाइयों को चाहते हैं)।

उपरोक्त हाइबरनेट समाधान से थोड़ा अधिक कोड हो सकता है, लेकिन आपका आवेदन अन्य जेपीए विक्रेताओं को पोर्टेबल होना चाहिए।

एक तरफ के रूप में, ओपनजेपीए FetchGroups (जेडीओ से उधार ली गई अवधारणा) का उपयोग कर उपरोक्त हाइबरनेट समाधान के लिए समान कार्यक्षमता प्रदान करता है।

एक आखिरी चेतावनी, FetchType।LAZY जेपीए में एक संकेत है, यदि आवश्यक हो तो प्रदाता पंक्तियों को उत्सुकता से लोड कर सकता है।

प्रति अनुरोध अपडेट किया गया।

इस तरह एक इकाई पर विचार करें:

@Entity 
public class ErrorCode { 
    // . . . 
    @OneToMany(fetch=FetchType.EAGER) // default fetch is LAZY for Collections 
    private Collection myCollection; 
    // . . . 
} 

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

<entity-mappings> 
    <entity class="ErrorCode"> 
     <attributes> 
      <one-to-many name="myCollection" fetch="LAZY"/> 
     </attributes> 
    </entity> 
</entity-mappings> 

और persistence.xml इस तरह दिखेगा:

<persistence> 
    <persistence-unit name="dao-eager"> 
     <!-- 
      . . . 
     --> 
    </persistence-unit> 

    <persistence-unit name="dao-lazy"> 
     <!-- 
      . . . 
      --> 
     <mapping-file>orm-lazy.xml</mapping-file> 
    </persistence-unit> 
</persistence> 
+0

माइक, क्या आप वास्तव में दो मैपिंग फाइलों की आवश्यकता नहीं है, पर आप अधिक विस्तार से जा सकते हैं, आप इकाई में एनोटेशन के रूप में या तो लाज़ी या ईगर निर्दिष्ट कर सकते हैं और फिर एक एक्सएमएल मैपिंग फ़ाइल में विपरीत निर्दिष्ट कर सकते हैं "? –

+0

मैंने एक त्वरित उदाहरण जोड़ा है। आशा करता हूँ की ये काम करेगा। – Mike

+0

एनोटेशन को बदलने के लिए हम एक्सएमएल को संपादित करेंगे, इकाई ऑब्जेक्ट को संपादित करने की तरह काफी है। हालांकि यह मेरे पास सबसे अच्छा विकल्प हो सकता है। –

1

के बाद से कोई भी OpenJPA उल्लेख किया है, मैं यहाँ एक जवाब डाल देंगे।

OpenJPA, में पहले से आलसी के लिए कॉन्फ़िगर संग्रह और क्षेत्रों बेसब्री से नीचे के रूप में लोड किया जा सकता

OpenJPAEntityManager kem = OpenJPAPersistence.cast(em); 
    kem.getFetchPlan().addField(Order.class, "products"); 
    TypedQuery<Order> query = kem.createQuery(yourQuery, Order.class); 

संदर्भ: http://openjpa.apache.org/builds/1.0.3/apache-openjpa-1.0.3/docs/manual/ref_guide_fetch.html

0

JPA2 में मैं EntityGraphs उपयोग करते हैं, जो कि तुम क्या निर्धारित कर सकते हैं संबंधित संस्थाएं जिन्हें आप पुनर्प्राप्त करना चाहते हैं:

https://docs.oracle.com/javaee/7/tutorial/persistence-entitygraphs002.htm https://docs.oracle.com/javaee/7/tutorial/persistence-entitygraphs003.htm

आपने एक नामांकितQuery बनाया है जैसा आपने किया था, और आप कुंजी javax.persistence.loadgraph या javax.persistence.fetchgraph के साथ एक संकेत संलग्न करते हैं। यह ग्राफ में परिभाषित संबंधित इकाइयों को पुनर्प्राप्त करेगा। What is the diffenece between FETCH and LOAD for Entity graph of JPA?