JPA – Cascade Stratejileri

Cascade JPA içerisinde stratejileri nesneler arasındaki persist operasyonların birlikte davranışlarını belirler. Bunun anlamı bağlı olduğunuz nesnenin aynı persist operasyonundan geçip geçmemesidir.

Örnek verecek olursak aşağıdaki gibi bir entity yapımız olsun.

JPA cascade

JPA Cascade Stratejileri

Buna göre Student ve Address arasında OneToOne bir ilişki bulunmaktadır ve kod aşağıdaki gibidir.

Student Entity

    @Entity
    public class Student implements Serializable {
     
     @Id
     @GeneratedValue
     private Long id;
     private String name;
     
     @OneToOne
     private Address homeAddress = new Address();
    }

Address Entity

    @Entity
    public class Address implements Serializable {
     
     @Id
     @GeneratedValue
     private Long id;
     private String street;
    }

Yukarıdaki entity mimarisine aşağıdaki gibi bir işlem yapalım.

    Student student = new Student();
    student.setName("Ahmet");
    student.getHomeAddress().setStreet("Esentepe");
    entityManager.persist(student);

Bu durumda aşağıdaki gibi bir hata oluşacaktır.

    15:16:05,160 INFO  [STDOUT] Hibernate:
        insert
        into
            Student
            (homeAddress_id, name)
        values
            (?, ?)
    15:16:05,187 WARN  [arjLoggerI18N] [com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator_2] TwoPhaseCoordinator.beforeCompletion – failed for com.arjuna.ats.internal.jta.resources.arjunacore.SynchronizationImple@64635b
    java.lang.IllegalStateException: org.hibernate.TransientObjectException: object references an unsaved transient instance – save the transient instance before flushing: org.domain.uekaetestiki.entity.Student.homeAddress -> org.domain.uekaetestiki.entity.Address
     at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:611)

Hatanın asıl nedeni aşağıdaki gibi.

    java.lang.IllegalStateException: org.hibernate.TransientObjectException: object references an unsaved transient instance – save the transient instance before flushing

Bunun nedeni Student içerisinde bulunan adresin student ile birlikte kaydedilmesi ancak address in kayıtlı bir nesne olmamasıdır. Yani buradaki nesne managed değil transient durumda beklemektedir.

Bu çözmek için iki yöntemimiz bulunuyor. Birincisi aşağıdaki gibi Student entity sini kaydetmeden önce Address i kaydetmektir.

    Student student = new Student();
    student.setName("Ahmet");
    student.getHomeAddress().setStreet("Esentepe");
    entityManager.persist(student.getHomeAddress());
    entityManager.persist(student);

Ancak birden fazla bağlayıcılığı olan entity lerde bu durum karmaşıklığa neden olabilir. Bu durumda Cascade stratejilerini kullanabiliriz.

Aşağıdaki örnekte Student -> Address ilişkisinde PERSIST tipinde bir cascade stratejisi verilmektedir.

    @OneToOne(cascade = CascadeType.PERSIST)
    private Address homeAddress = new Address();

Bu durumda Student tipindeki entity nesnelerinde bir persist operasyonu gerçekleşirse Address içinde aynı operasyon yapılacaktır. Yani entityManager.persist(student) dediğimiz anda iki adet insert cümleciği olacaktır.
Bunun haricinde Cascade tipleri persist, merge, remove, refresh ve all şeklinde de verilmektedir.

Tip Tanım
PERSIST Nesne persist edilirse alt nesne de persist edilir
MERGE Nesne merge edilirse alt nesne de merge edilir
REMOVE Nesne silinirse bağlı alt nesne de silinir
REFRESH Nesne yenilenirse bağlı alt nesne de yenilenir
ALL Tüm işlemler birlikte yapılır

Buna göre stratejiyi örnek olarak REMOVE verecek olursak Student nesnesinden bir kayıt sildiğimizde ilişklili adresi de silinecektir.
ALL tüm işlemler için geçerlidir tüm özellikleri taşır. Ancak tamamının olmasını istemiyorsak ve sadece PERSIST ve MERGE operasyonlarının birlikte yapılmasını düşünüyorsak bu durumda aşağıdaki gibi birden fazla tanımı kullanabiliriz.

    @OneToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE })
    private Address homeAddress = new Address();

Not : Silme işlemlerinde Cascade kullanımlarına dikkat ediniz. Bunları manuel yapmamızda fayda var.

No comments yet.

Leave a comment

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>