JPA'da CascadeType.REMOVE ve orphanRemoval arasındaki fark nedir?


107

Arasındaki fark nedir

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

ve

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

Bu örnek Java EE Tutorial'dan alınmıştır, ancak hala ayrıntıları anlamıyorum.


Yetim kaldırma, bağımlı varlıkların "ana" varlıkları ile ilişkisi ortadan kalktığında kaldırılması anlamına gelir.
Rahul Tripathi

1
Kavramı açıklayabilecek bir test senaryosu yazdı .
Martin Andersson

Yanıtlar:


155

Gönderen burada : -

Basamaklı Kaldır

CascadeType.REMOVE (veya REMOVE içeren CascadeType.ALL) ile bir referans alanını işaretlemek, kaldırma işlemlerinin o alan tarafından referans verilen varlık nesnelerine otomatik olarak basamaklandırılması gerektiğini gösterir (birden çok varlık nesnesine bir koleksiyon alanı tarafından başvurulabilir):

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

Yetim Kaldırma

JPA 2, @OneToOne ve @OneToMany ek açıklamalarının orphanRemoval öğesi kullanılarak belirtilebilen ek ve daha agresif bir kaldırma basamaklı modunu destekler:

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

FARK: -

İki ayar arasındaki fark, bir ilişkinin kesilmesine verilen yanıttır. Örneğin, adres alanını boş veya başka bir Adres nesnesine ayarlarken olduğu gibi.

  • Eğer orphanRemoval = true isimli belirtilen bağlantısız Adres örneği otomatik olarak kaldırılır. Bu, bir sahip nesneden (örn. Çalışan) referans olmadan var olmaması gereken bağımlı nesneleri (örn. Adres) temizlemek için kullanışlıdır.
  • Yalnızca cascade = CascadeType.REMOVE belirtilirse, bir ilişkinin bağlantısının kesilmesi bir kaldırma
    işlemi olmadığı için hiçbir otomatik eylem gerçekleştirilmez.

90

CascadeType.REMOVEVe arasındaki farkı anlamanın kolay bir yolu orphanRemoval=true.

Yetim kaldırma için: Çağırırsanız setOrders(null), ilgili Ordervarlıklar veritabanında otomatik olarak kaldırılacaktır.

Remove kaskad için: çağırmak durumunda setOrders(null), ilgili Orderkişiler olacaktır DEĞİL otomatik db kaldırılacaktır.


2
kaldır === sil
Abdull

11

Bir alt varlığımız ve bir ana varlığımız olduğunu varsayalım. Bir ebeveynin birkaç çocuğu olabilir.

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

OrphanRemoval bir ORM konseptidir, çocuğun öksüz olup olmadığını söyler. ayrıca veritabanından kaldırılmalıdır.

Ebeveyninden erişilemeyen çocuk yetim kalmıştır. Örneğin, Kişi nesneleri setini kaldırırsak (boş bir sete ayarlarsak) veya yeni bir setle değiştirirsek, ebeveyn artık eski setteki çocuklara erişemez ve çocuklar öksüz kalır, böylece çocuklar olmaya mahkum olur. veritabanında da kaldırılır.

CascadeType.REMOVE, veritabanı düzeyinde bir kavramdır ve üst öğe kaldırılırsa, alt tablodaki tüm ilgili kayıtlarının kaldırılması gerektiğini söyler.


Bu cevap daha mantıklı görünüyor, sonra bu başlıktaki herhangi bir cevap.
Jignesh M. Khatri

2

Pratik olarak fark, verileri güncellemeye mi (PATCH) yoksa verileri tamamen değiştirmeye mi (PUT) bağlıdır.

Diyelim ki customerkullanmaktan silerseniz, cascade=REMOVEkasıtlı ve yararlı görünen müşteri siparişleri de kaldırılır.

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

Şimdi diyelim ki, bir customerile güncellemeniz, orphanRemoval="true"önceki tüm siparişleri silecek ve bunları sağlananla değiştirecektir. ( PUTaçısından REST API)

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

orphanRemovalEski emirler olmazsa muhafaza edilirdi. ( PATCHaçısından REST API)


1

Bu soru çok yaygın olduğu için bu cevap blogumda yazdığım bu makaleye dayanmaktadır .

CascadeType.REMOVE

CascadeType.REMOVEAçıkça yapılandırabilirsiniz strateji,:

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

veya dolaylı olarak CascadeType.ALLstratejiden miras alır :

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

removeişlemi ana varlıktan alt varlıklarına yaymanıza olanak tanır .

Dolayısıyla, ana Postvarlığı commentskoleksiyonuyla birlikte getirirsek ve postvarlığı kaldırırsak :

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);

Hazırda bekletme üç silme ifadesini yürütecek:

DELETE FROM post_comment 
WHERE id = 2

DELETE FROM post_comment 
WHERE id = 3

DELETE FROM post 
WHERE id = 1

Alt PostCommentvarlıklar, alt varlıkları da CascadeType.REMOVEkaldırmışız gibi davranan strateji nedeniyle silindi .

Yetim kaldırma stratejisi

orphanRemovalÖznitelik aracılığıyla ayarlanması gereken yetim kaldırma stratejisi :

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

koleksiyondan alt varlığı kaldırdıktan sonra alt tablo satırını kaldırmanıza izin verir.

Demek ki yüklerseniz Postonun yanında varlık commentstoplama ve birinci kaldırmak PostCommentgelen commentskoleksiyonunda:

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));

Hibernate, ilişkili post_commenttablo satırı için bir DELETE deyimi yürütecek :

DELETE FROM post_comment 
WHERE id = 2

Bu konu hakkında daha fazla ayrıntı için bu makaleye de göz atın.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.