हाइबरनेट में दृढ़ता () बनाम बचत () का क्या फायदा है?


जवाबों:


154

से इस मंच पोस्ट

persist()अच्छी तरह से परिभाषित है। यह एक क्षणिक उदाहरण को निरंतर बनाता है। हालाँकि, यह गारंटी नहीं देता है कि पहचानकर्ता मान को लगातार उदाहरण के लिए सौंपा जाएगा, असाइनमेंट फ्लश समय पर हो सकता है। युक्ति यह नहीं कहती है, कि मेरे पास जो समस्या है persist()

persist()यह भी गारंटी देता है कि यदि यह लेनदेन सीमाओं के बाहर कहा जाता है तो यह INSERT विवरण को निष्पादित नहीं करेगा। यह एक विस्तारित सत्र / दृढ़ता के संदर्भ में लंबे समय तक चलने वाली बातचीत में उपयोगी है।

जैसी विधि persist()आवश्यक है।

save()उसी की गारंटी नहीं देता है, यह एक पहचानकर्ता देता है, और यदि पहचानकर्ता (जैसे "पहचान" जनरेटर, "अनुक्रम" नहीं) को प्राप्त करने के लिए एक INSERT को निष्पादित करना पड़ता है, तो यह INSERT तुरंत होता है, भले ही आप अंदर या बाहर हों। एक लेन-देन। विस्तारित सत्र / दृढ़ता के संदर्भ में लंबे समय तक चलने वाली बातचीत में यह अच्छा नहीं है।


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

क्या आपका मतलब है कि निरंतर () पद्धति इकाई को अलग अवस्था में बनाएगी और संलग्न अवस्था में सेव () करेगी?
rekinyz

2
मैंने हाल ही में दोनों का उपयोग किया और एक-से-कई द्वि-दिशात्मक मानचित्रण में बना रहा। मुझे पता चला कि सेव बच्चे को कैस्केड नहीं करता है, यानी, केवल माता-पिता को बचाया जाता है / टेबल में डाला जाता है। हालाँकि, माता-पिता और बच्चे दोनों को एक कॉल में बचाने का काम पूरा किया। मैं एक समग्र आईडी का उपयोग कर रहा हूं न कि उत्पन्न आईडी।
अरन-अर्न

68

मैंने अपने स्थानीय मशीन पर इसे चलाने सहित कई बार सेव () बनाम परसिस्ट () पर अच्छा शोध किया है। पिछले सभी स्पष्टीकरण भ्रमित कर रहे हैं और सही नहीं हैं। मैंने गहन शोध के बाद नीचे दिए गए बचाओ () और दृढ़ता () की तुलना की है।

Save()

  1. बचत के बाद रिटर्न जेनरेट हुआ। इसका Serializableवापसी प्रकार।
  2. लेनदेन के बाहर db में परिवर्तन सहेजें।
  3. उस निकाय को निर्दिष्ट निकाय में निर्दिष्ट करता है जिसे आप बना रहे हैं
  4. किसी अलग ऑब्जेक्ट के लिए Session.save () तालिका में एक नई पंक्ति बनाएगा।

Persist()

  1. बचत करने के बाद उत्पन्न आईडी वापस नहीं करता है। इसका शून्य वापसी प्रकार।
  2. लेनदेन के बाहर db में परिवर्तनों को सहेजता नहीं है।
  3. generated idउस इकाई को असाइन करता है जिसे आप जारी रख रहे हैं
  4. session.persist()एक अलग वस्तु के लिए फेंक दिया जाएगा PersistentObjectExceptionक्योंकि यह अनुमति नहीं है।

इन सभी पर परीक्षण / परीक्षण किया जाता है Hibernate v4.0.1


Save () और Persist () के लिए पॉइंट 3 का उल्लेख किया गया है लेकिन वे वास्तव में समान नहीं हैं। पर्सिस्ट () विधि लेनदेन के बाहर db में परिवर्तन को भी बचाती है।
रवि.कुमार

2
जब मैं लगातार विधि मान का उपयोग करके लेन-देन करने के बाद परीक्षण किया गया तो DB को नहीं बचाया जाता है
लक्ष्मीनारायण चल्लगोंडा

तो # 1 और # 5 दोनों के बीच वास्तविक अंतर हैं? यदि आपको किसी आईडी की आवश्यकता है या एक नई पंक्ति बनाई गई है, तो उपयोग करें Save()?
user2490003

How to Save () # 3 बाहर लेनदेन संभव है
vikas singh

24

मैं कुछ नकली परीक्षण किया save()और के बीच अंतर रिकॉर्ड करने के लिए persist()

लगता है कि इन दोनों तरीकों से समान व्यवहार किया जाता है जब क्षणिक इकाई के साथ व्यवहार किया जाता है, लेकिन अलग-अलग तरीके से काम किया जाता है।

नीचे दिए गए उदाहरण के लिए, EmployeeVehicle को PK के साथ एक इकाई के रूप में लें, vehicleIdजो कि एक उत्पन्न मूल्य है और vehicleNameइसके गुणों में से एक है।

उदाहरण 1: क्षणिक वस्तु से निपटना

Session session = factory.openSession();
session.beginTransaction();
EmployeeVehicle entity = new EmployeeVehicle();
entity.setVehicleName("Honda");
session.save(entity);
// session.persist(entity);
session.getTransaction().commit();
session.close();

परिणाम:

select nextval ('hibernate_sequence') // This is for vehicle Id generated : 36
insert into Employee_Vehicle ( Vehicle_Name, Vehicle_Id) values ( Honda, 36)

ध्यान दें कि जब आप पहले से बनी हुई वस्तु प्राप्त करते हैं और उसे सहेजते हैं, तो परिणाम वही होता है

EmployeeVehicle entity =  (EmployeeVehicle)session.get(EmployeeVehicle.class, 36);
entity.setVehicleName("Toyota");
session.save(entity);    -------> **instead of session.update(entity);**
// session.persist(entity);

उसी का उपयोग करते हुए दोहराएं persist(entity)और नए आईडी (37, हांडा) के साथ समान परिणाम देगा;

उदाहरण 2: डिटैच किए गए ऑब्जेक्ट से निपटना

// Session 1 
// Get the previously saved Vehicle Entity 
Session session = factory.openSession();
session.beginTransaction();
EmployeeVehicle entity = (EmployeeVehicle)session.get(EmployeeVehicle.class, 36);
session.close();

// Session 2
// Here in Session 2 , vehicle entity obtained in previous session is a detached object and now we will try to save / persist it 
// (i) Using Save() to persist a detached object 
Session session2 = factory.openSession();
session2.beginTransaction();
entity.setVehicleName("Toyota");
session2.save(entity);
session2.getTransaction().commit();
session2.close();

परिणाम: आपको आईडी के साथ वाहन की उम्मीद हो सकती है: पिछले सत्र में प्राप्त 36 को "टोयोटा" नाम से अपडेट किया गया है। लेकिन ऐसा क्या होता है कि डीबी में एक नई इकाई को बचाया जाता है और "टोयोटा" नाम के साथ नई आईडी बनाई जाती है।

select nextval ('hibernate_sequence')
insert into Employee_Vehicle ( Vehicle_Name, Vehicle_Id) values ( Toyota, 39)

अलग किए गए अस्तित्व को बनाए रखने के लिए दृढ़ता का उपयोग करना

// (ii) Using Persist()  to persist a detached
// Session 1 
Session session = factory.openSession();
session.beginTransaction();
EmployeeVehicle entity = (EmployeeVehicle)session.get(EmployeeVehicle.class, 36);
session.close();

// Session 2
// Here in Session 2 , vehicle entity obtained in previous session is a detached object and now we will try to save / persist it 
// (i) Using Save() to persist a detached
Session session2 = factory.openSession();
session2.beginTransaction();
entity.setVehicleName("Toyota");
session2.persist(entity);
session2.getTransaction().commit();
session2.close();

परिणाम:

Exception being thrown : detached entity passed to persist

इसलिए, Save () के बजाय Persist () का उपयोग करना हमेशा बेहतर होता है क्योंकि Transient ऑब्जेक्ट से निपटने के दौरान सेव का सावधानीपूर्वक उपयोग करना होता है।

महत्वपूर्ण नोट: उपरोक्त उदाहरण में, वाहन इकाई का पीके एक उत्पन्न मूल्य है, इसलिए जब एक अलग इकाई को बनाए रखने के लिए बचत () का उपयोग करते हुए हाइबरनेट बने रहने के लिए एक नई आईडी बनाता है। हालाँकि अगर यह pk एक उत्पन्न मान नहीं है, तो इसका परिणाम एक अपवाद बताते हुए कुंजी का उल्लंघन है।


13

हाइबरनेट में विभिन्न दृढ़ता विधियों के बारे में इस प्रश्न के कुछ अच्छे उत्तर हैं। अपने प्रश्न का सीधे उत्तर देने के लिए, ट्रांज़ैक्शन स्टेट की परवाह किए बिना, तुरंत () सम्मिलित विवरण को निष्पादित किया जाता है। यह सम्मिलित कुंजी देता है ताकि आप ऐसा कुछ कर सकें:

long newKey = session.save(myObj);

तो तुरंत उपयोग करें () यदि आपको लगातार उदाहरण के लिए असाइन किए गए पहचानकर्ता की आवश्यकता है।

दृढ़ता () के साथ, सम्मिलित विवरण को लेनदेन में निष्पादित किया जाता है, जरूरी नहीं कि तुरंत। यह ज्यादातर मामलों में बेहतर है।

यदि आप लेन-देन के साथ आउट-ऑफ-सीक्वेंस होने के लिए इन्सर्ट की आवश्यकता नहीं है, तो फ़िस्टिस्ट () का उपयोग करें और आपको सम्मिलित की गई कुंजी की आवश्यकता नहीं है।


6

यहां वे अंतर हैं जो आपको लगातार रहने और बचाने के तरीकों को समझने में मदद कर सकते हैं:

  • बचत और हठ के बीच पहला अंतर उनकी वापसी का प्रकार है। वापसी प्रकार की बनी रहती विधि शून्य है जबकि वापसी प्रकार की बचत
    विधि सीरियलाइज़ेबल ऑब्जेक्ट है।
  • दृढ़ता () विधि यह गारंटी नहीं देती है कि पहचानकर्ता का मूल्य तुरंत स्थिर स्थिति को सौंपा जाएगा, असाइनमेंट फ्लश समय पर हो सकता है।

  • यदि यह लेन-देन सीमाओं के बाहर कहा जाता है, तो persist () विधि किसी सम्मिलित क्वेरी को निष्पादित नहीं करेगी। हालांकि, सहेजें () पद्धति एक पहचानकर्ता लौटाती है ताकि पहचानकर्ता को प्राप्त करने के लिए एक सम्मिलित क्वेरी तुरंत निष्पादित हो, भले ही वह लेनदेन के अंदर या बाहर हो।

  • हठ पद्धति को लेनदेन सीमाओं के बाहर कहा जाता है, यह एक विस्तारित सत्र संदर्भ के साथ लंबे समय तक चलने वाली बातचीत में उपयोगी है। दूसरी ओर विस्तारित सत्र संदर्भ के साथ लंबे समय से चल रही बातचीत में सेव विधि अच्छी नहीं है।

  • हाइबरनेट में बचत और हठ विधि के बीच पांचवां अंतर: हठ जेपीए द्वारा समर्थित है, जबकि बचत केवल हाइबरनेट द्वारा समर्थित है।

आप हाइबरनेट में सहेजने और जारी रखने की विधि के बीच अंतर से पूर्ण कामकाजी उदाहरण देख सकते हैं


पहले आप कहते हैं कि "जारी () लेनदेन प्रविष्टि सीमाओं को निष्पादित नहीं करेगा यदि इसे लेनदेन सीमाओं के बाहर कहा जाता है"। फिर आप कहते हैं "दृढ़ता पद्धति को लेन-देन की सीमाओं के बाहर कहा जाता है, यह लंबे समय से चल रही बातचीत में विस्तारित SIA संदर्भ के साथ उपयोगी है।" क्या वे विरोधाभासी नहीं हैं? मुझे समझ नहीं आ रहा है।
कुमार मनीष

@KumarManish लगातार विधि के मामले में, एक आवेषण क्वेरी फ्लश समय पर होती है। इसलिए यह लंबे समय से चल रही बातचीत में एक सर्वोत्तम प्रथा है
डेविड फाम

5

save () - जैसा कि विधि नाम से पता चलता है, इकाई को डेटाबेस में सहेजने के लिए हाइबरनेट सेव () का उपयोग किया जा सकता है। हम एक लेनदेन के बाहर इस विधि को लागू कर सकते हैं। यदि हम बिना लेन-देन के इसका उपयोग करते हैं और हमारे पास संस्थाओं के बीच कास्केडिंग है, तो केवल प्राथमिक इकाई तब तक बच जाती है जब तक हम सत्र को फ्लश नहीं करते।

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


5

यहाँ अंतर है:

  1. सहेजें:

    1. डेटाबेस में ऑब्जेक्ट सहेजे जाने पर आईडी / पहचानकर्ता वापस कर देगा।
    2. जब ऑब्जेक्ट को अलग करने के बाद एक नया सत्र खोलकर ऐसा करने की कोशिश की जाएगी तब भी बचत होगी।
  2. जारी रहती है:

    1. जब ऑब्जेक्ट डेटाबेस में सहेजा जाता है तो शून्य हो जाएगा।
    2. जब एक नए सत्र के माध्यम से अलग वस्तु को बचाने की कोशिश की PersistentObjectException फेंक देंगे।

क्या आप किसी स्निपेट के साथ एक उदाहरण दिखा सकते हैं। वह उपयोगी होगा।
Avikool91

5

मूल नियम कहता है कि:

उत्पन्न पहचानकर्ता के साथ संस्थाओं के लिए:

save (): यह ऑब्जेक्ट को स्थायी बनाने के अलावा एक इकाई के पहचानकर्ता को तुरंत लौटाता है। तो एक सम्मिलित क्वेरी को तुरंत निकाल दिया जाता है।

persist (): यह लगातार ऑब्जेक्ट को लौटाता है। पहचानकर्ता को तुरंत लौटाने की उसकी कोई मजबूरी नहीं है, इसलिए यह गारंटी नहीं देता कि डालने पर तुरंत निकाल दिया जाएगा। यह तुरंत एक सम्मिलित आग लगा सकता है लेकिन इसकी गारंटी नहीं है। कुछ मामलों में, क्वेरी को तुरंत निकाल दिया जा सकता है जबकि अन्य में इसे सत्र फ्लश समय पर निकाल दिया जा सकता है।

निर्दिष्ट पहचानकर्ता के साथ संस्थाओं के लिए:

save (): यह किसी इकाई के पहचानकर्ता को तुरंत लौटाता है। चूंकि पहचानकर्ता कॉल बचाने से पहले ही इकाई को सौंपा गया है, इसलिए सम्मिलित तुरंत नहीं निकाल दिया जाता है। इसे सत्र फ्लश समय पर निकाल दिया जाता है।

persist (): as save यह भी फ्लश समय पर आग डालने।

मान लीजिए कि हमारे पास एक इकाई है जो एक उत्पन्न पहचानकर्ता का उपयोग इस प्रकार करता है:

@Entity
@Table(name="USER_DETAILS")
public class UserDetails {
    @Id
    @Column(name = "USER_ID")
    @GeneratedValue(strategy=GenerationType.AUTO)
    private int userId;

    @Column(name = "USER_NAME")
    private String userName;

    public int getUserId() {
        return userId;
    }
    public void setUserId(int userId) {
        this.userId = userId;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
}

सहेजें() :

    Session session = sessionFactory.openSession();
    session.beginTransaction();
    UserDetails user = new UserDetails();
    user.setUserName("Gaurav");
    session.save(user); // Query is fired immediately as this statement is executed.
    session.getTransaction().commit();
    session.close();

लगातार ():

    Session session = sessionFactory.openSession();
    session.beginTransaction();
    UserDetails user = new UserDetails();
    user.setUserName("Gaurav");
    session.persist(user); // Query is not guaranteed to be fired immediately. It may get fired here.
    session.getTransaction().commit(); // If it not executed in last statement then It is fired here.
    session.close();

अब मान लें कि हमारे पास एक ही इकाई है जो आईडी फ़ील्ड जनरेट किए बिना एनोटेशन के रूप में परिभाषित की गई है अर्थात आईडी को मैन्युअल रूप से सौंपा जाएगा।

@Entity
@Table(name="USER_DETAILS")
public class UserDetails {
    @Id
    @Column(name = "USER_ID")
    private int userId;

    @Column(name = "USER_NAME")
    private String userName;

    public int getUserId() {
        return userId;
    }
    public void setUserId(int userId) {
        this.userId = userId;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
}

बचाने के लिए ():

Session session = sessionFactory.openSession();
session.beginTransaction();
UserDetails user = new UserDetails();
user.setUserId(1);
user.setUserName("Gaurav");
session.save(user); // Query is not fired here since id for object being referred by user is already available. No query need to be fired to find it. Data for user now available in first level cache but not in db.
session.getTransaction().commit();// Query will be fired at this point and data for user will now also be available in DB
session.close();

जारी रखने के लिए ():

Session session = sessionFactory.openSession();
session.beginTransaction();
UserDetails user = new UserDetails();
user.setUserId(1);
user.setUserName("Gaurav");
session.persist(user); // Query is not fired here.Object is made persistent. Data for user now available in first level cache but not in db.
session.getTransaction().commit();// Query will be fired at this point and data for user will now also be available in DB
session.close();

उपरोक्त मामले तब सही थे जब किसी लेनदेन के भीतर से बचत या दृढ़ता को बुलाया गया था।

सहेजें और जारी रखने के बीच अंतर के अन्य बिंदु हैं:

  1. save () को ट्रांजेक्शन के बाहर कहा जा सकता है। यदि असाइन किए गए पहचानकर्ता का उपयोग किया जाता है तो चूंकि आईडी पहले से उपलब्ध है, इसलिए कोई सम्मिलित क्वेरी तुरंत निकाल नहीं दी जाती है। क्वेरी को केवल निकाल दिया जाता है जब सत्र को फ़्लश किया जाता है।

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

  3. यदि दृढ़ता () लेन-देन से बाहर है, तो सम्मिलित केवल तभी निकाल दिया जाता है जब सत्र को निकाल दिया जाता है, इससे कोई फर्क नहीं पड़ता कि किस प्रकार के पहचानकर्ता (उत्पन्न या असाइन किए गए) का उपयोग किया जाता है।

  4. यदि सेव को लगातार ऑब्जेक्ट पर कहा जाता है, तो अपडेट क्वेरी का उपयोग करके इकाई को बचाया जाता है।


2

दरअसल, हाइबरनेट सेव () और पर्सिस्ट () विधियों के बीच का अंतर जनरेटर क्लास पर निर्भर करता है जिसका हम उपयोग कर रहे हैं।
यदि हमारा जनरेटर वर्ग सौंपा गया है, तो सेव () और पर्सिस्ट () तरीकों में कोई अंतर नहीं है। क्योंकि जनरेटर 'असाइन' का अर्थ है, एक प्रोग्रामर के रूप में, हमें डेटाबेस में सहेजने के लिए प्राथमिक कुंजी मान देने की आवश्यकता है [आशा है कि आप इस जनरेटर अवधारणा को जानते हैं] सौंपा जनरेटर वर्ग के अलावा अन्य मामलों में, मान लें कि हमारे जनरेटर वर्ग का नाम वृद्धि का मतलब है हाइबरनेट स्वयं डेटाबेस में प्राथमिक कुंजी आईडी मान देगा [नियत जनरेटर के अलावा, हाइबरनेट केवल प्राथमिक कुंजी आईडी मान को याद रखने के लिए उपयोग किया जाता है], इसलिए इस मामले में अगर हम सेव () या पर्सिस्ट () विधि कहते हैं, तो यह सामान्य रूप से डेटाबेस में रिकॉर्ड सम्मिलित करेगा।
लेकिन यहां, बात यह है कि, सहेजें () विधि उस प्राथमिक कुंजी आईडी मान को वापस कर सकती है जो हाइबरनेट द्वारा उत्पन्न होता है और हम इसे
लंबे s = session.save (k) द्वारा देख सकते हैं ;
इस मामले में, ग्राहक () किसी भी मूल्य को ग्राहक को वापस नहीं देगा, रिटर्न प्रकार शून्य।
persist () यह भी गारंटी देता है कि यदि यह लेनदेन सीमाओं के बाहर कहा जाता है तो यह INSERT विवरण को निष्पादित नहीं करेगा।
जबकि बचा () में, INSERT तुरंत होता है, भले ही आप लेनदेन के अंदर या बाहर हों।


1

किसी भी इकाई को संग्रहीत करते समय आईडी में "जनरेटर" प्रकार के आधार पर इसका पूरी तरह से उत्तर दिया गया। यदि जनरेटर के लिए मान "असाइन किया गया" है, जिसका अर्थ है कि आप आईडी की आपूर्ति कर रहे हैं। तब यह हाइबरनेट को बचाने या बनाए रखने में कोई अंतर नहीं करता है। आप अपनी मनचाही विधि से जा सकते हैं। यदि मान "असाइन नहीं किया गया" है और आप सेव () का उपयोग कर रहे हैं, तो आपको सेव (रिटर्न) से रिटर्न के रूप में आईडी मिल जाएगी।

एक और जाँच यह है कि क्या आप लेन-देन की सीमा से बाहर ऑपरेशन कर रहे हैं या नहीं। क्योंकि हाइबरनेट के लिए बचना () जेपीए के अंतर्गत आता है। इसलिए ट्रांज़िस्ट सीमाओं के बाहर दृढ़ता () का उपयोग करना ऐसा करने की अनुमति नहीं देगा और दृढ़ता से संबंधित अपवाद को फेंक देगा। बचत के साथ () ऐसा कोई प्रतिबंध नहीं है और एक डीबी लेनदेन के साथ लेनदेन सीमा के बाहर () के माध्यम से जा सकता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.