JPA में CascadeType.REMOVE और orphanRemoval के बीच क्या अंतर है?


100

के बीच क्या अंतर है

@OneToMany(cascade=REMOVE, mappedBy="customer")
public List<Order> getOrders() { ... }

तथा

@OneToMany(mappedBy="customer", orphanRemoval="true")
public List<Order> getOrders() { ... }

यह उदाहरण जावा ईई ट्यूटोरियल से है, लेकिन मुझे अभी भी विवरण समझ में नहीं आया है।


अनाथ निष्कासन का अर्थ है कि आश्रित निकाय को हटा दिया जाता है जब उनकी "मूल" इकाई से संबंध नष्ट हो जाता है।
राहुल त्रिपाठी

1
एक परीक्षण मामला लिखा जो अवधारणा को स्पष्ट कर सकता है।
मार्टिन एंडरसन 15

जवाबों:


152

से यहाँ : -

कैस्केडिंग निकालें

CascadeType.REMOVE (या CascadeType.ALL, जिसमें REMOVE शामिल है) के साथ एक संदर्भ फ़ील्ड को चिह्नित करना इंगित करता है कि निकाय द्वारा निकाले जाने वाले ऑब्जेक्ट्स को स्वचालित रूप से कैस्केड किया जाना चाहिए जो उस फ़ील्ड द्वारा संदर्भित हैं (एकाधिक निकाय ऑब्जेक्ट्स को संग्रह फ़ील्ड द्वारा संदर्भित किया जा सकता है):

@Entity
class Employee {
     :
    @OneToOne(cascade=CascadeType.REMOVE)
    private Address address;
     :
}

अनाथ निकालना

JPA 2 एक अतिरिक्त और अधिक आक्रामक हटाने कैस्केडिंग मोड का समर्थन करता है जिसे @OneToOne और @OneToMany एनोटेशन के orphanRemoval तत्व का उपयोग करके निर्दिष्ट किया जा सकता है:

@Entity
class Employee {
     :
    @OneToOne(orphanRemoval=true)
    private Address address;
     :
}

अंतर:-

दो सेटिंग्स के बीच अंतर एक रिश्ते को डिस्कनेक्ट करने की प्रतिक्रिया में है। उदाहरण के लिए, जैसे पता फ़ील्ड को अशक्त करने के लिए या किसी अन्य पता ऑब्जेक्ट पर सेट करते समय।

  • यदि orphanRemoval = सही निर्दिष्ट किया गया है तो डिस्कनेक्ट किया गया पता उदाहरण स्वचालित रूप से हटा दिया जाता है। यह निर्भर वस्तुओं (जैसे पते) को साफ करने के लिए उपयोगी है जो एक मालिक वस्तु (जैसे कर्मचारी) के संदर्भ के बिना मौजूद नहीं होना चाहिए।
  • यदि केवल कैस्केड = CascadeType.REMOVE निर्दिष्ट किया जाता है, तो कोई स्वचालित कार्रवाई नहीं की जाती है क्योंकि किसी संबंध को डिस्कनेक्ट करना
    ऑपरेशन नहीं है ।

87

CascadeType.REMOVEऔर के बीच अंतर को समझने का एक आसान तरीका orphanRemoval=true

अनाथ हटाने के लिए: यदि आप आह्वान करते हैं setOrders(null), तो संबंधित Orderनिकाय अपने आप ही db में हटा दिए जाएंगे।

कैस्केड हटाने के लिए: यदि आप आह्वान करते हैं setOrders(null), तो संबंधित Orderनिकाय अपने आप डीबी में नहीं हटाए जाएंगे।


2
निकालें === हटा
अब्दुल्ला

9

मान लीजिए हमारे पास एक बाल इकाई और एक मूल संस्था है। एक माता-पिता के कई बच्चे हो सकते हैं।

@Entity
class parent {
  //id and other fields
 @OneToMany (orphanRemoval = "true",cascade = CascadeType.REMOVE)
   Set<Person> myChildern;
}

OrphanRemoval एक ORM अवधारणा है, यह बताता है कि क्या बच्चा अनाथ है। इसे डेटाबेस से भी हटा दिया जाना चाहिए।

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

CascadeType.REMOVE एक डेटाबेस स्तर की अवधारणा है और यह बताता है कि क्या माता-पिता को हटा दिया गया है, चाइल्ड टेबल में इसके सभी संबंधित रिकॉर्ड को हटा दिया जाना चाहिए।


2

व्यावहारिक रूप से अंतर यह है कि क्या आप डेटा (PATCH) को अपडेट करने की कोशिश कर रहे हैं या पूरी तरह से डेटा (PUT) को बदल देते हैं

मान लीजिए कि आप customerउपयोग करने की तुलना में डिलीट करते हैं , cascade=REMOVEउन ग्राहकों के आदेशों को भी हटा देगा जो इच्छित और उपयोगी लगते हैं।

@OneToMany(cascade=REMOVE, mappedBy="customer")
public List<Order> getOrders() { ... }

अब कहते हैं कि आप इसे अपडेट करते हैं customer, orphanRemoval="true"यह पिछले सभी आदेशों को हटा देगा और उन्हें प्रदान किए गए के साथ बदल देगा। ( PUTके संदर्भ में REST API)

@OneToMany(mappedBy="customer", orphanRemoval="true")
public List<Order> getOrders() { ... }

बिना orphanRemovalपुराने आदेश के रखा जाएगा। ( PATCHके संदर्भ में REST API)


1

चूँकि यह प्रश्न बहुत ही सामान्य है, यह उत्तर इस लेख पर आधारित है जो मैंने अपने ब्लॉग पर लिखा था।

CascadeType.REMOVE

CascadeType.REMOVEरणनीति है, जो आपको स्पष्ट रूप से कॉन्फ़िगर कर सकते हैं:

@OneToMany(
    mappedBy = "post",
    cascade = CascadeType.REMOVE
)
private List<PostComment> comments = new ArrayList<>();

या यह CascadeType.ALLरणनीति से निहित है :

@OneToMany(
    mappedBy = "post",
    cascade = CascadeType.ALL
)
private List<PostComment> comments = new ArrayList<>();

आपको removeमूल संस्था से इसकी बाल संस्थाओं तक के संचालन का प्रचार करने की अनुमति देता है।

इसलिए, यदि हम Postइसके commentsसंग्रह के साथ मूल इकाई को प्राप्त करते हैं , और postइकाई को हटा देते हैं :

Post post = entityManager.createQuery("""
    select p
    from Post p
    join fetch p.comments
    where p.id = :id
    """, Post.class)
.setParameter("id", postId)
.getSingleResult();

entityManager.remove(post);

हाइबरनेट तीन डिलीट स्टेटमेंट को निष्पादित करने वाला है:

DELETE FROM post_comment 
WHERE id = 2

DELETE FROM post_comment 
WHERE id = 3

DELETE FROM post 
WHERE id = 1

PostCommentबच्चे संस्थाओं की वजह से नष्ट कर दिया गया CascadeType.REMOVEरणनीति है, जो के रूप में अगर हम बच्चे संस्थाओं के रूप में अच्छी तरह से हटा दिया काम किया।

अनाथ-हटाने की रणनीति

अनाथ-निष्कासन रणनीति, जिसे orphanRemovalविशेषता के माध्यम से सेट करने की आवश्यकता है :

@OneToMany(
    mappedBy = "post",
    cascade = CascadeType.ALL,
    orphanRemoval = true
)
private List<PostComment> comments = new ArrayList<>();

आपको संग्रह से बाल इकाई को हटाने पर चाइल्ड टेबल रो को हटाने की अनुमति देता है।

इसलिए, यदि हम Postइकाई को उसके commentsसंग्रह के साथ लोड करते हैं और संग्रह PostCommentसे पहली हटाते हैं comments:

Post post = entityManager.createQuery("""
    select p
    from Post p
    join fetch p.comments c
    where p.id = :id
    order by p.id, c.id
    """, Post.class)
.setParameter("id", postId)
.getSingleResult();

post.remove(post.getComments().get(0));

हाइबरनेट संबंधित post_commentतालिका पंक्ति के लिए DELETE विवरण निष्पादित करने जा रहा है :

DELETE FROM post_comment 
WHERE id = 2

इस विषय के बारे में अधिक जानकारी के लिए, इस लेख को भी देखें।

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