JPA EntityManager: Neden merge() yerine persist() kullanılmalı?

EntityManager.merge()` yeni nesneler ekleyebilir ve var olanları güncelleyebilir.

Neden persist() (yalnızca yeni nesneler oluşturabilir) kullanılmak istensin ki?

Çözüm

Her iki yöntem de bir PersistenceContext'e bir varlık ekler, aradaki fark daha sonra varlıkla ne yapacağınızdır.

Persist, bir varlık örneğini alır, bağlama ekler ve bu örneği yönetilebilir hale getirir (yani, varlıkta gelecekte yapılacak güncellemeler izlenir).

Merge, varlığınızın yeni bir örneğini oluşturur, durumu sağlanan varlıktan kopyalar ve yeni kopyayı yönetilir hale getirir. İlettiğiniz örnek yönetilmeyecektir (yaptığınız herhangi bir değişiklik işlemin bir parçası olmayacaktır - tekrar merge çağrısı yapmadığınız sürece).

Belki bir kod örneği yardımcı olabilir.

MyEntity e = new MyEntity();

// scenario 1
// tran starts
em.persist(e); 
e.setSomeField(someValue); 
// tran ends, and the row for someField is updated in the database

// scenario 2
// tran starts
e = new MyEntity();
em.merge(e);
e.setSomeField(anotherValue); 
// tran ends but the row for someField is not updated in the database
// (you made the changes *after* merging)

// scenario 3
// tran starts
e = new MyEntity();
MyEntity e2 = em.merge(e);
e2.setSomeField(anotherValue); 
// tran ends and the row for someField is updated
// (the changes were made to e2, not e)

Senaryo 1 ve 3 kabaca eşdeğerdir, ancak Senaryo 2'yi kullanmak isteyeceğiniz bazı durumlar vardır.

Yorumlar (12)

em.mergekullandığımda, JPA'nın benim için oluşturduğu bir alan olmasa bile, herINSERTiçin birSELECTifadesi aldığımı fark ettim - birincil anahtar alanı kendi belirlediğim bir UUID idi. em.persist(myEntityObject) seçeneğine geçtim ve o zaman sadece INSERT deyimleri aldım.

Yorumlar (2)

Oturumda olan lazy loaded bir koleksiyona erişmeye çalıştığım için varlığımda lazyLoading özel durumları alıyordum.

Yaptığım şey, ayrı bir istekte bulunmak, oturumdan varlığı almak ve ardından jsp sayfamdaki bir koleksiyona erişmeye çalışmaktı ki bu sorunluydu.

Bunu hafifletmek için, aynı varlığı denetleyicimde güncelledim ve jsp'me aktardım, ancak oturumda yeniden kaydettiğimde SessionScope aracılığıyla da erişilebilir olacağını ve bir LazyLoadingException atmayacağını hayal ediyorum, örnek 2'nin bir modifikasyonu:

Aşağıdakiler benim işime yaradı:

// scenario 2 MY WAY
// tran starts
e = new MyEntity();
e = em.merge(e); // re-assign to the same entity "e"

//access e from jsp and it will work dandy!!
Yorumlar (0)