Apa keuntungan dari persist () vs save () di Hibernate?

Jawaban:

154

Dari pos forum ini

persist()didefinisikan dengan baik. Itu membuat contoh sementara persisten. Namun, itu tidak menjamin bahwa nilai pengidentifikasi akan segera diberikan ke contoh persisten, penugasan mungkin terjadi pada waktu flush. Spec tidak mengatakan itu, yang merupakan masalah yang saya miliki persist().

persist()juga menjamin bahwa itu tidak akan menjalankan pernyataan INSERT jika itu disebut di luar batas transaksi. Ini berguna dalam percakapan jangka panjang dengan konteks Sesi / persistensi yang diperpanjang.

Diperlukan metode seperti persist().

save()tidak menjamin hal yang sama, ia mengembalikan pengenal, dan jika INSERT harus dijalankan untuk mendapatkan pengenal (mis. generator "identitas", bukan "urutan"), INSERT ini segera terjadi, tidak peduli apakah Anda di dalam atau di luar sebuah transaksi. Ini tidak baik dalam percakapan jangka panjang dengan sesi Sesi / ketekunan yang diperpanjang.

Bala R
sumber
44
untuk menambahkan lebih banyak dari pos yang sama, untuk mengeluh: "Sayangnya, 5 tahun kemudian, utas ini masih menjadi satu-satunya sumber informasi yang jelas tentang subjek ini. Dokumentasi Hibernate, sementara verbose, tidak memiliki semua kecuali informasi penggunaan yang paling sepele. Mengapa posting terakhir christian tidak ada dalam Sesi javadoc hanyalah misteri dokumentasi Hibernate lainnya. "
kommradHomer
maksud Anda metode bertahan () akan membuat entitas dalam keadaan terlepas dan save () dalam keadaan terlampir?
rekinyz
2
Saya baru-baru ini menggunakan save dan bertahan dalam pemetaan dua arah satu-ke-banyak. Saya menemukan bahwa menyimpan tidak mengalir ke anak, yaitu, hanya Induk disimpan / dimasukkan dalam tabel. Namun, tetap menyelesaikan tugas menyelamatkan Orang Tua dan Anak dalam satu panggilan. Saya menggunakan ID komposit bukan ID yang dihasilkan.
arn-arn
68

Saya telah melakukan penelitian yang baik pada save () vs bertahan () termasuk menjalankannya di mesin lokal saya beberapa kali. Semua penjelasan sebelumnya membingungkan dan tidak benar. Saya telah membandingkan save () dan bertahan () di bawah setelah penelitian menyeluruh.

Save()

  1. Mengembalikan ID yang dihasilkan setelah menyimpan. Its Serializabletipe kembali.
  2. simpan perubahan ke db di luar transaksi.
  3. Tetapkan id yang dihasilkan untuk entitas yang Anda miliki
  4. Session.save () untuk objek yang terpisah akan membuat baris baru di tabel.

Persist()

  1. Tidak mengembalikan Id yang dihasilkan setelah menyimpan. Jenis kembali tidak valid.
  2. Tidak menyimpan perubahan ke db di luar transaksi.
  3. Tetapkan generated iduntuk entitas yang Anda tahan
  4. session.persist()untuk objek yang terlepas akan melempar PersistentObjectExceptionkarena tidak diizinkan.

Semua ini dicoba / diuji Hibernate v4.0.1.

Zeus
sumber
Poin 3 untuk Save () dan Persist () disebutkan tetapi sebenarnya tidak sama. Metode Persist () menyimpan perubahan ke db di luar transaksi juga.
Ravi.Kumar
2
ketika saya diuji setelah melakukan transaksi menggunakan metode persist, nilai tidak disimpan ke DB
Laxminarayana Challagonda
Jadi # 1 dan # 5 adalah perbedaan nyata antara keduanya? Jika Anda membutuhkan id yang dikembalikan atau baris baru dibuat, gunakan Save()?
user2490003
Bagaimana Simpan () # 3 dimungkinkan di luar transaksi
vikas singh
24

Saya melakukan beberapa pengujian tiruan untuk mencatat perbedaan antara save()dan persist().

Kedengarannya seperti kedua metode ini berperilaku sama ketika berhadapan dengan Entitas Transien tetapi berbeda ketika berhadapan dengan Entitas Terpisah.

Untuk contoh di bawah ini, ambil EmployeeVehicle sebagai Entity dengan PK vehicleIdyang merupakan nilai yang dihasilkan dan vehicleNamesebagai salah satu propertinya.

Contoh 1: Berurusan dengan Objek Transient

Session session = factory.openSession();
session.beginTransaction();
EmployeeVehicle entity = new EmployeeVehicle();
entity.setVehicleName("Honda");
session.save(entity);
// session.persist(entity);
session.getTransaction().commit();
session.close();

Hasil:

select nextval ('hibernate_sequence') // This is for vehicle Id generated : 36
insert into Employee_Vehicle ( Vehicle_Name, Vehicle_Id) values ( Honda, 36)

Perhatikan hasilnya sama ketika Anda mendapatkan objek yang sudah ada dan menyimpannya

EmployeeVehicle entity =  (EmployeeVehicle)session.get(EmployeeVehicle.class, 36);
entity.setVehicleName("Toyota");
session.save(entity);    -------> **instead of session.update(entity);**
// session.persist(entity);

Ulangi penggunaan yang sama persist(entity)dan akan menghasilkan hal yang sama dengan Id baru (katakanlah 37, honda);

Contoh 2: Berurusan dengan Obyek Terpisah

// Session 1 
// Get the previously saved Vehicle Entity 
Session session = factory.openSession();
session.beginTransaction();
EmployeeVehicle entity = (EmployeeVehicle)session.get(EmployeeVehicle.class, 36);
session.close();

// Session 2
// Here in Session 2 , vehicle entity obtained in previous session is a detached object and now we will try to save / persist it 
// (i) Using Save() to persist a detached object 
Session session2 = factory.openSession();
session2.beginTransaction();
entity.setVehicleName("Toyota");
session2.save(entity);
session2.getTransaction().commit();
session2.close();

Hasil: Anda mungkin mengharapkan Kendaraan dengan id: 36 yang diperoleh di sesi sebelumnya diperbarui dengan nama "Toyota". Tetapi yang terjadi adalah bahwa entitas baru disimpan dalam DB dengan ID baru yang dihasilkan untuk dan Nama sebagai "Toyota"

select nextval ('hibernate_sequence')
insert into Employee_Vehicle ( Vehicle_Name, Vehicle_Id) values ( Toyota, 39)

Menggunakan bertahan untuk bertahan entitas terpisah

// (ii) Using Persist()  to persist a detached
// Session 1 
Session session = factory.openSession();
session.beginTransaction();
EmployeeVehicle entity = (EmployeeVehicle)session.get(EmployeeVehicle.class, 36);
session.close();

// Session 2
// Here in Session 2 , vehicle entity obtained in previous session is a detached object and now we will try to save / persist it 
// (i) Using Save() to persist a detached
Session session2 = factory.openSession();
session2.beginTransaction();
entity.setVehicleName("Toyota");
session2.persist(entity);
session2.getTransaction().commit();
session2.close();

Hasil:

Exception being thrown : detached entity passed to persist

Jadi, selalu lebih baik menggunakan Persist () daripada Save () karena save harus digunakan dengan hati-hati ketika berhadapan dengan objek Transient.

Catatan Penting: Dalam contoh di atas, pk entitas kendaraan adalah nilai yang dihasilkan, jadi ketika menggunakan save () untuk bertahan entitas yang terpisah, hibernate menghasilkan id baru untuk bertahan. Namun jika pk ini bukan nilai yang dihasilkan daripada itu menghasilkan pengecualian yang menyatakan kunci dilanggar.

Deivanayagam Senthil
sumber
12

Pertanyaan ini memiliki beberapa jawaban bagus tentang berbagai metode kegigihan di Hibernate. Untuk menjawab pertanyaan Anda secara langsung, dengan save () pernyataan penyisipan dieksekusi segera terlepas dari kondisi transaksi. Ini mengembalikan kunci yang dimasukkan sehingga Anda dapat melakukan sesuatu seperti ini:

long newKey = session.save(myObj);

Jadi gunakan save () jika Anda membutuhkan pengenal yang ditugaskan untuk instance persistent segera.

Dengan bertahan (), pernyataan insert dieksekusi dalam transaksi, tidak harus segera. Ini lebih disukai dalam banyak kasus.

Gunakan bertahan () jika Anda tidak perlu memasukkan untuk keluar dari urutan dengan transaksi dan Anda tidak perlu memasukkan kunci dikembalikan.

CFL_Jeff
sumber
6

Berikut adalah perbedaan yang dapat membantu Anda memahami keunggulan metode bertahan dan menyimpan:

  • Perbedaan pertama antara menyimpan dan bertahan adalah jenis pengembalian mereka. Jenis kembali dari metode bertahan adalah batal sementara jenis kembali dari
    metode simpan adalah objek Serializable.
  • Metode persist () tidak menjamin bahwa nilai pengidentifikasi akan segera ditetapkan ke status persisten, penugasan mungkin terjadi pada waktu flush.

  • Metode bertahan () tidak akan menjalankan kueri sisipan jika itu disebut di luar batas transaksi. Sementara itu, metode save () mengembalikan pengidentifikasi sehingga permintaan memasukkan dieksekusi segera untuk mendapatkan pengenal, tidak peduli apakah itu di dalam atau di luar transaksi.

  • Metode bertahan disebut di luar batas transaksi, ini berguna dalam percakapan jangka panjang dengan konteks Sesi diperpanjang. Di sisi lain, metode save tidak bagus dalam percakapan jangka panjang dengan konteks Sesi yang diperpanjang.

  • Perbedaan kelima antara metode save dan persist di Hibernate: persist didukung oleh JPA, sementara save hanya didukung oleh Hibernate.

Anda dapat melihat contoh kerja penuh dari pos Perbedaan antara metode simpan dan bertahan di Hibernate

David Pham
sumber
Pertama, Anda mengatakan "Metode bertahan () tidak akan menjalankan kueri sisipan jika itu disebut di luar batas transaksi". Lalu Anda berkata "Metode bertahan disebut di luar batas transaksi, ini berguna dalam percakapan jangka panjang dengan konteks Sesi diperpanjang." Bukankah mereka bertentangan? Saya tidak mengerti.
Kumar Manish
@KumarManish Dalam kasus metode bertahan, permintaan memasukkan terjadi pada waktu flush. Jadi ini adalah praktik terbaik dalam percakapan jangka panjang
David Pham
5

save () - Seperti yang disarankan oleh nama metode, hibernate save () dapat digunakan untuk menyimpan entitas ke basis data. Kami dapat meminta metode ini di luar transaksi. Jika kami menggunakan ini tanpa transaksi dan kami memiliki cascading antara entitas, maka hanya entitas utama yang akan disimpan kecuali kami menyiram sesi.

persist () - Hibernate persist mirip dengan save (with transaction) dan ia menambahkan objek entitas ke konteks persisten, sehingga setiap perubahan lebih lanjut dilacak. Jika properti objek diubah sebelum transaksi dilakukan atau sesi dibilas, itu juga akan disimpan ke dalam basis data. Selain itu, kita dapat menggunakan metode persist () hanya dalam batas transaksi, sehingga aman dan menangani objek yang bertingkat. Akhirnya, bertahan tidak mengembalikan apa pun sehingga kita perlu menggunakan objek yang ada untuk mendapatkan nilai pengenal yang dihasilkan.

Rohit Goyal
sumber
5

Inilah perbedaannya:

  1. menyimpan:

    1. akan mengembalikan id / pengidentifikasi ketika objek disimpan ke database.
    2. juga akan menyimpan ketika objek mencoba melakukan hal yang sama dengan membuka sesi baru setelah terlepas.
  2. Bertahan:

    1. akan kembali batal ketika objek disimpan ke database.
    2. akan membuang PersistentObjectException ketika mencoba menyimpan objek yang dilepaskan melalui sesi baru.
Mohammed Amin
sumber
Tolong tunjukkan contoh dengan cuplikan. Itu akan bermanfaat.
Avikool91
5

Aturan dasar mengatakan bahwa:

Untuk Entitas dengan pengidentifikasi yang dihasilkan:

save (): Ini mengembalikan pengenal entitas segera selain membuat objek tetap. Jadi permintaan memasukkan dipecat segera.

persist (): Ini mengembalikan objek persisten. Ia tidak memiliki paksaan untuk mengembalikan pengidentifikasi segera sehingga tidak menjamin bahwa insert akan segera dipecat. Ini dapat mem-api insert segera tetapi tidak dijamin. Dalam beberapa kasus, kueri dapat dipecat segera sementara dalam kasus lain itu dapat dipecat pada waktu sesi flush.

Untuk Entitas dengan pengidentifikasi yang ditugaskan:

save (): Ini mengembalikan pengenal entitas segera. Karena pengenal sudah ditetapkan ke entitas sebelum memanggil save, jadi insert tidak langsung dipecat. Ini dipecat pada waktu sesi flush.

bertahan (): sama seperti menyimpan. Ini juga api masukkan pada waktu flush.

Misalkan kita memiliki entitas yang menggunakan pengenal yang dihasilkan sebagai berikut:

@Entity
@Table(name="USER_DETAILS")
public class UserDetails {
    @Id
    @Column(name = "USER_ID")
    @GeneratedValue(strategy=GenerationType.AUTO)
    private int userId;

    @Column(name = "USER_NAME")
    private String userName;

    public int getUserId() {
        return userId;
    }
    public void setUserId(int userId) {
        this.userId = userId;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
}

simpan ():

    Session session = sessionFactory.openSession();
    session.beginTransaction();
    UserDetails user = new UserDetails();
    user.setUserName("Gaurav");
    session.save(user); // Query is fired immediately as this statement is executed.
    session.getTransaction().commit();
    session.close();

bertahan ():

    Session session = sessionFactory.openSession();
    session.beginTransaction();
    UserDetails user = new UserDetails();
    user.setUserName("Gaurav");
    session.persist(user); // Query is not guaranteed to be fired immediately. It may get fired here.
    session.getTransaction().commit(); // If it not executed in last statement then It is fired here.
    session.close();

Sekarang anggaplah kita memiliki entitas yang sama didefinisikan sebagai berikut tanpa bidang id telah menghasilkan anotasi yaitu ID akan diberikan secara manual.

@Entity
@Table(name="USER_DETAILS")
public class UserDetails {
    @Id
    @Column(name = "USER_ID")
    private int userId;

    @Column(name = "USER_NAME")
    private String userName;

    public int getUserId() {
        return userId;
    }
    public void setUserId(int userId) {
        this.userId = userId;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
}

untuk save ():

Session session = sessionFactory.openSession();
session.beginTransaction();
UserDetails user = new UserDetails();
user.setUserId(1);
user.setUserName("Gaurav");
session.save(user); // Query is not fired here since id for object being referred by user is already available. No query need to be fired to find it. Data for user now available in first level cache but not in db.
session.getTransaction().commit();// Query will be fired at this point and data for user will now also be available in DB
session.close();

untuk bertahan ():

Session session = sessionFactory.openSession();
session.beginTransaction();
UserDetails user = new UserDetails();
user.setUserId(1);
user.setUserName("Gaurav");
session.persist(user); // Query is not fired here.Object is made persistent. Data for user now available in first level cache but not in db.
session.getTransaction().commit();// Query will be fired at this point and data for user will now also be available in DB
session.close();

Kasus di atas benar ketika menyimpan atau bertahan dipanggil dari dalam suatu transaksi.

Perbedaan lain antara save dan bertahan adalah:

  1. save () dapat dipanggil di luar transaksi. Jika pengenal yang ditugaskan digunakan maka sejak id sudah tersedia, jadi tidak ada permintaan memasukkan segera dipecat. Kueri hanya dipecat ketika sesi memerah.

  2. Jika pengenal yang dihasilkan digunakan, maka karena id perlu dibuat, masukkan segera dipecat. Tapi itu hanya menyelamatkan entitas utama. Jika entitas memiliki beberapa entitas berjenjang maka mereka tidak akan disimpan dalam db pada saat ini. Mereka akan disimpan ketika sesi dibilas.

  3. Jika bertahan () di luar transaksi maka masukkan dipecat hanya ketika sesi memerah tidak peduli apa pun jenis pengenal (dihasilkan atau ditugaskan) digunakan.

  4. Jika simpan disebut melalui objek persisten, maka entitas disimpan menggunakan kueri pembaruan.

Gaurav Kumar
sumber
2

Sebenarnya, perbedaan antara metode hibernate save () dan persist () bergantung pada kelas generator yang kami gunakan.
Jika kelas generator kami ditetapkan, maka tidak ada perbedaan antara metode save () dan persist (). Karena generator 'ditugaskan' berarti, sebagai seorang programmer kita perlu memberikan nilai kunci primer untuk disimpan dalam database dengan benar [Harap Anda tahu konsep generator ini] Dalam kasus selain dari kelas generator yang ditugaskan, misalkan jika nama kelas generator kita adalah Increment means hibernate sendiri akan menetapkan nilai id kunci primer ke dalam basis data tepat [selain generator yang ditugaskan, hibernasi hanya digunakan untuk menjaga nilai id kunci primer ingat], jadi dalam hal ini jika kita memanggil metode save () atau persist (), maka itu akan memasukkan catatan ke dalam basis data secara normal.
Tapi di sini, masalahnya, metode save () dapat mengembalikan nilai id kunci primer yang dihasilkan oleh hibernate dan kita bisa melihatnya dengan
long s = session.save (k);
Dalam kasus yang sama, persist () tidak akan pernah memberikan nilai apa pun kembali ke klien, jenis kembali batal.
bertahan () juga menjamin bahwa itu tidak akan menjalankan pernyataan INSERT jika itu disebut di luar batas transaksi.
sedangkan di save (), INSERT segera terjadi, tidak peduli apakah Anda di dalam atau di luar transaksi.

Hari Krishna
sumber
1

Itu benar-benar menjawab berdasarkan tipe "generator" di ID saat menyimpan entitas apa pun. Jika nilai untuk generator "ditetapkan" yang berarti Anda memberikan ID. Maka tidak ada bedanya hibernate untuk menyimpan atau bertahan. Anda dapat menggunakan metode apa pun yang Anda inginkan. Jika nilai tidak "ditetapkan" dan Anda menggunakan save () maka Anda akan mendapatkan ID sebagai pengembalian dari operasi save ().

Pemeriksaan lain adalah apakah Anda melakukan operasi di luar batas transaksi atau tidak. Karena persist () milik JPA sementara save () untuk hibernate. Jadi menggunakan persist () di luar batas-batas transaksi tidak akan memungkinkan untuk melakukannya dan melempar pengecualian yang terkait dengan persistent. sementara dengan save () tidak ada batasan seperti itu dan seseorang dapat pergi dengan transaksi DB melalui save () di luar batas transaksi.

Neeraj
sumber