JPA / EJB कोड के साथ "अलग-थलग रहने वाली इकाई त्रुटि को बनाए रखने के लिए पारित"


81

मैं इस मूल JPA / EJB कोड को चलाने का प्रयास कर रहा हूं:

public static void main(String[] args){
         UserBean user = new UserBean();
         user.setId(1);
         user.setUserName("name1");
         user.setPassword("passwd1");
         em.persist(user);
  }

मुझे यह त्रुटि मिली:

javax.ejb.EJBException: javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: com.JPA.Database

कोई विचार?

मैं इंटरनेट पर खोज करता हूं और मैंने जो कारण पाया वह था:

यह इस कारण से था कि आपने वस्तुओं का निर्माण कैसे किया, अर्थात यदि आप आईडी संपत्ति को स्पष्ट रूप से निर्धारित करते हैं। आईडी असाइनमेंट को हटाकर इसे ठीक कर दिया गया।

लेकिन मुझे यह नहीं मिला, कोड काम करने के लिए मुझे क्या संशोधित करना होगा?

जवाबों:


50

अर्ड

चलो कहते हैं कि तुम दो संस्थाओं है Albumऔर Photo। एल्बम में कई तस्वीरें होती हैं, इसलिए यह एक से कई रिश्ते हैं।

एल्बम वर्ग

@Entity
public class Album {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    Integer albumId;

    String albumName;

    @OneToMany(targetEntity=Photo.class,mappedBy="album",cascade={CascadeType.ALL},orphanRemoval=true)
    Set<Photo> photos = new HashSet<Photo>();
}

फोटो क्लास

@Entity
public class Photo{
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    Integer photo_id;

    String photoName;

    @ManyToOne(targetEntity=Album.class)
    @JoinColumn(name="album_id")
    Album album;

}

दृढ़ता या मर्ज करने से पहले आपको क्या करना है, प्रत्येक तस्वीरों में एल्बम संदर्भ सेट करना है।

        Album myAlbum = new Album();
        Photo photo1 = new Photo();
        Photo photo2 = new Photo();

        photo1.setAlbum(myAlbum);
        photo2.setAlbum(myAlbum);       

इससे पहले कि आप बने रहें या मर्ज करें, संबंधित इकाई को कैसे संलग्न करें।


2
यदि आप जेनेरिक का उपयोग करते हैं, तो "targetEntity = Photo.class" का उपयोग करने की कोई आवश्यकता नहीं है
रोलरबॉल

hi, photo1 nad photo2 पर एल्बम ऑब्जेक्ट सेट करने के बाद ... हमें फ़ोटो या एल्बम की सूची को सहेजने के लिए क्या ऑब्जेक्ट है?
दिलंका रत्नायके

130

त्रुटि तब होती है क्योंकि ऑब्जेक्ट का ID सेट है। हाइबरनेट क्षणिक और अलग की गई वस्तुओं के बीच अंतर persistकरता है और केवल क्षणिक वस्तुओं के साथ काम करता है। यदि persistनिष्कर्ष निकाला जाता है कि वस्तु को अलग किया गया है (जो कि आईडी निर्धारित होने के कारण है), तो वह "त्रुटि के लिए जारी की गई अलग वस्तु" वापस कर देगी। आप और अधिक जानकारी प्राप्त कर सकते यहाँ और यहाँ

हालांकि, यह केवल तभी लागू होता है जब आपने प्राथमिक कुंजी को ऑटो-जनरेट करने के लिए निर्दिष्ट किया है: यदि फ़ील्ड को हमेशा मैन्युअल रूप से सेट करने के लिए कॉन्फ़िगर किया गया है, तो यह कोड काम करता है।


क्या मैं कहता हूं कि तकनीकी रूप से सही होगा, मैं जेपीए का उपयोग कर रहा हूं और हाइबरनेट का नहीं, इसलिए कि उपरोक्त कथन सही नहीं होना चाहिए? मैं JPA में नौसिखिया हूं (सटीक होने के लिए 3 ays: P)
zengr

Sun का JPA Javadoc ( java.sun.com/javaee/5/docs/api/javax/persistence/… ) और टॉपलिंक का स्वरूप बिल्कुल एक जैसा है और सुझाव है कि आप तकनीकी रूप से सही हैं। हालांकि, यह वास्तव में उबलता है कि विनिर्देश क्या कहता है () व्यवहार करना चाहिए और दुख की बात है, मुझे नहीं पता कि वह क्या है।
टॉमिस्लाव नैक-अल्फेयरविक

इस समाधान ने मेरे लिए काम किया। मैं एक वस्तु को बनाए रख रहा था, आईडी को कहीं स्टोर करके रखा था। मैं तब उस मौजूदा वस्तु को एक नए मूल्य के साथ अधिलेखित करना चाहता हूं, इसलिए मैंने ऑब्जेक्ट बनाया, आईडी को वापस कॉपी किया और जब मैंने बचाने की कोशिश की तो यह विस्फोट हो गया। अंत में, मुझे DB (findById) की आवश्यकता थी, परिवर्तन करें, और फिर उस वस्तु को बनाए रखें ।
cs94njw


12

मुझे जवाब मिला, मैं उपयोग कर रहा था:

em.persist(user);

मैंने हठ के स्थान पर मर्ज किया:

em.merge(user);

लेकिन पता नहीं, क्यों बनी हुई है काम नहीं किया। :(


11
यह समाधान नहीं है!
अम्मार बोजोर्वर

1
मुझे पता है, लेकिन यह मेरे लिए काम करता है। यहाँ कोई अन्य उत्तर जो आपके लिए काम करता है? यदि हाँ, तो मैं इसे चुनने के लिए अधिक से अधिक खुश रहूंगा।
zengr

4
यह काम किया क्योंकि आपकी वस्तु हाइबरनेट सत्र से अलग हो गई थी या ऑब्जेक्ट क्षणिक है लेकिन हाइबरनेट इसे अलग किए हुए के रूप में देखता है क्योंकि आपको प्राथमिक कुंजी घोषित की गई है, मर्ज का उपयोग करने के साथ आप ऑब्जेक्ट को संलग्न करते हैं सत्र वह फिर से आपको अपने डेटाबेस में ऑब्जेक्ट्स को अपडेट करने में सक्षम बनाता है। ; देखें: docs.jboss.org/hibernate/core/3.3/reference/en/html/…
बेन

11

यदि आप id = GenerationType.AUTOअपनी इकाई में रणनीति उत्पन्न करने के लिए उपयोग करते हैं।

user.setId (1)द्वारा प्रतिस्थापित user.setId (null), और समस्या हल हो गई है।


5

मुझे पता है कि बहुत देर हो चुकी है और हर किसी को जवाब मिल गया है। लेकिन इसे जोड़ने के लिए थोड़ा और अधिक: जब GenerateType सेट किया गया है, तो किसी ऑब्जेक्ट पर जारी () एक आईडी प्राप्त होने की उम्मीद है।

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

अगर आईडी शून्य है - इस स्थिति में एक शून्य सूचक अपवाद तब उठाया जाता है जब प्रकार ऑटो या पहचान पत्र आदि होता है जब तक कि आईडी एक तालिका या सेक्सेस आदि से उत्पन्न नहीं होती है।

डिजाइन: यह तब होता है जब तालिका में प्राथमिक कुंजी के रूप में एक सेम संपत्ति होती है। GenerateType को केवल तभी सेट किया जाना चाहिए जब कोई आईडी स्वतःपूर्ण हो। इसे निकालें और इन्सर्ट को यूजर द्वारा निर्दिष्ट आईडी के साथ काम करना चाहिए। (यह एक प्राथमिक प्राथमिक क्षेत्र के लिए मैप की गई संपत्ति का खराब डिजाइन है)


5

यहां .persist () केवल रिकॉर्ड सम्मिलित करेगा। यदि हम .merge () का उपयोग करते हैं , तो यह जांच करेगा कि क्या वर्तमान आईडी के साथ कोई रिकॉर्ड मौजूद है, यदि यह मौजूद है, तो यह अपडेट होगा अन्यथा यह एक नया रिकॉर्ड सम्मिलित करेगा।


जब तक मुझे आपका जवाब नहीं मिला, तब तक मुझे एक टन समय लगा। आपका बहुत बहुत धन्यवाद!
थच वान

3

यदि आप अपने डेटाबेस में प्राथमिक कुंजी और निरंकुशता के लिए आईडी सेट करते हैं, तो कोड की यह पंक्ति गलत है:

user.setId(1);

इसके साथ प्रयास करें:

public static void main(String[] args){
         UserBean user = new UserBean();
         user.setUserName("name1");
         user.setPassword("passwd1");
         em.persist(user);
  }

मैंने कोशिश की और मुझे पता है कि यह त्रुटि हो रही है:detached entity passed to persist
s1ddok

2

मुझे यह समस्या थी और यह दूसरे स्तर के कैश के कारण था:

  1. मैंने हाइबरनेट का उपयोग करके एक इकाई कायम रखी
  2. फिर मैंने एक अलग प्रक्रिया से बनाई गई पंक्ति को हटा दिया जो दूसरे स्तर के कैश के साथ इंटरैक्ट नहीं करती थी
  3. मैंने उसी पहचानकर्ता के साथ एक और इकाई कायम रखी (मेरे पहचानकर्ता मान स्वतः उत्पन्न नहीं होते हैं)

इसलिए, क्योंकि कैश को अमान्य नहीं किया गया था, हाइबरनेट ने माना कि यह एक ही इकाई के एक अलग उदाहरण के साथ काम कर रहा था।

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