2010-05-05 13 views
22

जेपीए थोक आवेषण के बारे में कई विषयों को पढ़ने के बाद मैंने बनाया है, मेरे पास 2 लगातार ऑब्जेक्ट उपयोगकर्ता और साइट है। एक उपयोगकर्ता के पास कई साइट हो सकती है, इसलिए हमारे पास यहां कई संबंध हैं। मान लीजिए कि मैं उपयोगकर्ता बनाना चाहता हूं और उपयोगकर्ता खाते में कई साइटें बनाना/लिंक करना चाहता हूं। यहां साइट ऑब्जेक्ट्स के लिए थोक डालने का उपयोग करने के इच्छुक होने पर कोड कैसा दिखता है।जेपीए/हाइबरनेट थोक (बैच) डालें

User user = new User("John Doe"); 

user.getSites().add(new Site("google.com", user)); 
user.getSites().add(new Site("yahoo.com", user)); 

EntityTransaction tx = entityManager.getTransaction(); 
tx.begin(); 
entityManager.persist(user); 
tx.commit(); 

लेकिन जब मैं इस कोड को चलाने मैं एसक्यूएल उत्पादन निम्न देखें (मैं JPA कार्यान्वयन प्रदाता के रूप में हाइबरनेट उपयोग कर रहा हूँ):

Hibernate: insert into User (id, name) values (null, ?) 
Hibernate: call identity() 
Hibernate: insert into Site (id, url, user_id) values (null, ?, ?) 
Hibernate: call identity() 
Hibernate: insert into Site (id, url, user_id) values (null, ?, ?) 
Hibernate: call identity() 

तो, मैं इसका मतलब है 'असली' थोक काम करता है नहीं या मैं डालने मैं उलझन में हूं?

इस उदाहरण प्रोजेक्ट के लिए source code है, यह मेवेन प्रोजेक्ट है ताकि आप केवल आउटपुट जांचने के लिए एमवीएन इंस्टॉल डाउनलोड और चला सकें।

UPDATED:

डीबग: ऑर्ग

User user = new User("John Doe"); 
    user.getSites().add(new Site(1, "google.com", user)); 
    user.getSites().add(new Site(2, "yahoo.com", user)); 
    entityManager.setFlushMode(FlushModeType.COMMIT); 
    EntityTransaction tx = entityManager.getTransaction(); 
    tx.begin(); 
    entityManager.persist(user); 
    tx.commit(); 

अब मैं डिबग आउटपुट में निम्न पंक्ति है:

के बाद केन लियू कृपया सलाह देने के लिए, मैं विकलांग साइट ऑब्जेक्ट id ऑटो पीढ़ी है। hibernate.jdbc.AbstractBatcher - बैच आकार निष्पादित करना: 2

यह काम करता है!

उत्तर

19

यदि आप आईडी उत्पन्न करने के लिए डेटाबेस का उपयोग कर रहे हैं, तो प्रत्येक इकाई के लिए प्राथमिक कुंजी उत्पन्न करने के लिए हाइबरनेट को एक क्वेरी निष्पादित करना होगा।

+0

ओह, यह समझ में आता है! धन्यवाद – abovesun

+0

मैंने प्रश्न अपडेट किया है, क्या आप इसे देख सकते हैं, धन्यवाद – abovesun

+5

अब आप अपनी चाबियाँ कैसे बना रहे हैं? आपको यह सुनिश्चित करना होगा कि आपकी चाबियाँ अनूठी हैं। –

6

मैंने एक छोटा ब्लॉग लिखा है जो बैच डालने के बारे में बात करता है और छोटे परियोजना के लिए पॉइंटर भी है जिसमें हाइबरनेट के साथ बैच सम्मिलन के साथ शुरू करने के लिए सभी सही कॉन्फ़िगरेशन हैं। http://sensiblerationalization.blogspot.com/2011/03/quick-tip-on-hibernate-batch-operation.html

5

पर विवरण देखें मुझे थोक आवेषण के लिए हाइबरनेट को बाईपास करने के लिए और अधिक कुशलता मिली है। आपको ओआरएम (ऑब्जेक्ट रिलेशनल मैपिंग) से दूर होना चाहिए, लेकिन आप अभी भी मौजूदा सत्र और लेनदेन प्रबंधन से जुड़े कनेक्शन का लाभ उठा सकते हैं।

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

Session.doWork इसे सुविधाजनक बनाने के लिए बहुत आसान है।

private MyParentObject saveMyParentObject(final MyParentObject parent, final List<MyChildObject> children) 
{ 
    transaction = session.beginTransaction(); 
    try 
    { 
     session.save(parent); // NOTE: parent.parentId assigned and returned here 

     session.doWork(new Work() 
     { 
      public void execute(Connection con) throws SQLException 
      { 
       // hand written insert SQL - can't use hibernate 
       PreparedStatement st = con.prepareStatement("INSERT INTO my_child (parent_id, name, ...) values (?, ?, ...)"); 

       for (MyChildObject child : children) 
       { 
        MyChildObject child = new MyChildObject(); 
        child.setParentId(parent.getParentId()); // assign parent id for foreign key 

        // hibernate can't help, determine jdbc parameters manually 
        st.setLong(1, child.getParentId()); 
        st.setString(2, child.getName()); 
        ... 
        st.addBatch(); 
       } 

       // NOTE: you may want to limit the size of the batch 
       st.executeBatch(); 
      } 
     }); 

     // if your parent has a OneToMany relationship with child(s), refresh will populate this 
     session.refresh(parent); 
     transaction.commit(); 
     return parent; 
    } 
    catch(Throwable e) 
    { 
     transaction.rollback(); 
     throw new RuntimeException(e); 
    } 
} 
+1

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

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