Apa perbedaan antara persist () dan merge () di JPA dan Hibernate?

119

Apa perbedaan antara persist () dan merge () di Hibernate?

persist() dapat membuat kueri UPDATE & INSERT, misalnya:

SessionFactory sef = cfg.buildSessionFactory();
Session session = sef.openSession();
A a=new A();
session.persist(a);
a.setName("Mario");
session.flush();

dalam hal ini query akan dibuat seperti ini:

Hibernate: insert into A (NAME, ID) values (?, ?)
Hibernate: update A set NAME=? where ID=?

sehingga persist()metode dapat menghasilkan Sisipan dan Pembaruan.

Sekarang dengan merge():

SessionFactory sef = cfg.buildSessionFactory();
Session session = sef.openSession();
Singer singer = new Singer();
singer.setName("Luciano Pavarotti");
session.merge(singer);
session.flush();

Inilah yang saya lihat di database:

SINGER_ID   SINGER_NAME
1           Ricky Martin
2           Madonna
3           Elvis Presley
4           Luciano Pavarotti

Sekarang perbarui catatan menggunakan merge()

SessionFactory sef = cfg.buildSessionFactory();
Session session = sef.openSession();
Singer singer = new Singer();
singer.setId(2);
singer.setName("Luciano Pavarotti");
session.merge(singer);
session.flush();

Inilah yang saya lihat di database:

SINGER_ID   SINGER_NAME
1           Ricky Martin
2           Luciano Pavarotti
3           Elvis Presley
Jimit Tank
sumber
7
Javadoc sangat eksplisit tentang apa yang mereka lakukan, dan apa perbedaannya. Sudahkah Anda membaca dan memahaminya?
Skaffman

Jawaban:

144

Spesifikasi JPA berisi deskripsi semantik yang sangat tepat dari operasi ini, lebih baik daripada di javadoc:

Semantik operasi persist , yang diterapkan ke entitas X adalah sebagai berikut:

  • Jika X adalah entitas baru, itu menjadi terkelola. Entitas X akan dimasukkan ke dalam database pada atau sebelum melakukan transaksi atau sebagai hasil dari operasi pembilasan.

  • Jika X adalah entitas terkelola yang sudah ada, ini diabaikan oleh operasi persist. Namun, operasi tetap dialihkan ke entitas yang direferensikan oleh X, jika hubungan dari X ke entitas lain ini dianotasi dengan cascade=PERSISTatau cascade=ALL nilai elemen anotasi atau ditentukan dengan elemen deskriptor XML yang setara.

  • Jika X adalah entitas yang dihapus, itu menjadi dikelola.

  • Jika X adalah objek yang terlepas, EntityExistsExceptionmungkin terlempar saat operasi persist dipanggil, atau yang EntityExistsExceptionlain PersistenceExceptiondapat dilemparkan pada waktu flush atau commit.

  • Untuk semua entitas Y yang direferensikan oleh relasi dari X, jika relasi ke Y telah dianotasi dengan nilai elemen kaskade cascade=PERSISTatau cascade=ALL, operasi tetap diterapkan ke Y.


Semantik operasi penggabungan yang diterapkan ke entitas X adalah sebagai berikut:

  • Jika X adalah entitas yang terpisah, status X disalin ke instance entitas terkelola yang sudah ada sebelumnya X 'dengan identitas yang sama atau salinan terkelola baru X' dari X dibuat.

  • Jika X adalah instance entitas baru, instance entitas terkelola baru X 'dibuat dan status X disalin ke dalam instance entitas terkelola baru X'.

  • Jika X adalah instance entitas yang dihapus, sebuah IllegalArgumentExceptionakan dilempar oleh operasi penggabungan (atau komit transaksi akan gagal).

  • Jika X adalah entitas yang dikelola, itu diabaikan oleh operasi penggabungan, namun, operasi penggabungan dialihkan ke entitas yang direferensikan oleh hubungan dari X jika hubungan ini telah dianotasi dengan nilai elemen kaskade cascade=MERGEatau cascade=ALLanotasi.

  • Untuk semua entitas Y yang direferensikan oleh hubungan dari X yang memiliki nilai elemen kaskade cascade=MERGEatau cascade=ALL, Y digabungkan secara rekursif sebagai Y '. Untuk semua Y yang direferensikan oleh X, X 'diatur ke referensi Y'. (Perhatikan bahwa jika X dikelola maka X adalah objek yang sama dengan X '.)

  • Jika X adalah entitas yang digabungkan ke X ', dengan referensi ke entitas lain Y, di mana cascade=MERGEatau cascade=ALLtidak ditentukan, navigasi asosiasi yang sama dari X' menghasilkan referensi ke objek terkelola Y 'dengan identitas tetap yang sama seperti Y.

axtavt
sumber
Terimakasih atas infonya. Saya melihat semantik dari kedua definisi tersebut. Tetapi pertanyaannya adalah tentang perbedaan di antara mereka. Mungkin menyajikan daftar negara bagian dan 2 sub-bagian untuk setiap perilaku persistvs merge?
AlikElzin-kilaka
25

Ini berasal dari JPA. Dengan cara yang sangat sederhana:

  • persist(entity) harus digunakan dengan entitas yang benar-benar baru, untuk menambahkannya ke DB (jika entitas sudah ada di DB, akan ada lemparan EntityExistsException).

  • merge(entity) harus digunakan, untuk mengembalikan entitas ke konteks ketekunan jika entitas dilepas dan diubah.

Krystian
sumber
bisakah Anda menambahkan sumber untuk penjelasan Anda? Terima kasih.
AlikElzin-kilaka
@ AlikElzin-kilaka penjelasan demikian, seingat saya, saya temukan di buku "Beginning Java EE 7".
Krystian
12

Tetap harus dipanggil hanya pada entitas baru, sedangkan penggabungan dimaksudkan untuk melampirkan kembali entitas yang terpisah.

Jika Anda menggunakan generator yang ditetapkan, menggunakan merge dan bukan persist dapat menyebabkan pernyataan SQL yang berlebihan , sehingga memengaruhi performa.

Selain itu, memanggil gabungan untuk entitas yang dikelola juga merupakan kesalahan karena entitas yang dikelola secara otomatis dikelola oleh Hibernate dan status mereka disinkronkan dengan rekaman database dengan mekanisme pemeriksaan kotor saat membersihkan Konteks Persistensi .

Vlad Mihalcea
sumber
1

Perbedaan terpenting adalah ini:

  • Dalam kasus persistmetode, jika entitas yang akan dikelola dalam konteks persistensi, sudah ada dalam konteks persistensi, yang baru akan diabaikan. (Tidak ada yang terjadi)

  • Namun dalam kasus mergemetode, entitas yang telah dikelola dalam konteks persistensi akan diganti dengan entitas baru (diperbarui) dan salinan entitas yang diperbarui ini akan dikembalikan. (mulai sekarang setiap perubahan harus dilakukan pada entitas yang dikembalikan ini jika Anda ingin mencerminkan perubahan Anda dalam konteks ketekunan)

Od Chan
sumber