Hibernate Error: org.hibernate.NonUniqueObjectException: objek berbeda dengan nilai pengenal yang sama telah dikaitkan dengan sesi

114

Saya memiliki dua Objek pengguna dan ketika saya mencoba untuk menyimpan objek menggunakan

session.save(userObj);

Saya mendapatkan kesalahan berikut:

Caused by: org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session:
[com.pojo.rtrequests.User#com.pojo.rtrequests.User@d079b40b]

Saya membuat sesi menggunakan

BaseHibernateDAO dao = new BaseHibernateDAO();          

rtsession = dao.getSession(userData.getRegion(),
                           BaseHibernateDAO.RTREQUESTS_DATABASE_NAME);

rttrans = rtsession.beginTransaction();
rttrans.begin();

rtsession.save(userObj1);
rtsession.save(userObj2);

rtsession.flush();
rttrans.commit();

rtsession.close(); // in finally block

Saya juga mencoba melakukan session.clear()sebelum menabung, masih belum berhasil.

Ini untuk pertama kalinya saya mendapatkan objek sesi ketika permintaan pengguna datang, jadi saya mengerti mengapa mengatakan objek itu hadir dalam sesi.

Ada saran?

kasar
sumber
Berikut adalah utas bagus lainnya yang membantu menyelesaikan masalah saya getj2ee.over-blog.com/…
Reddymails

Jawaban:

173

Saya telah mengalami kesalahan ini berkali-kali dan cukup sulit untuk dilacak ...

Pada dasarnya, apa yang dikatakan hibernasi adalah Anda memiliki dua objek yang memiliki pengenal yang sama (kunci utama yang sama) tetapi keduanya bukan objek yang sama.

Saya sarankan Anda memecah kode Anda, yaitu mengomentari bit sampai kesalahan hilang dan kemudian mengembalikan kode sampai kembali dan Anda harus menemukan kesalahan.

Ini paling sering terjadi melalui penyimpanan bertingkat di mana ada penyimpanan bertingkat antara objek A dan B, tetapi objek B telah dikaitkan dengan sesi tetapi tidak pada contoh B yang sama seperti yang ada di A.

Generator kunci utama apa yang Anda gunakan?

Alasan saya bertanya adalah kesalahan ini terkait dengan bagaimana Anda memberi tahu hibernate untuk memastikan status persisten suatu objek (yaitu apakah suatu objek persisten atau tidak). Kesalahan bisa terjadi karena hibernasi mencoba mempertahankan objek yang sudah persisten. Faktanya, jika Anda menggunakan save hibernate akan mencoba dan mempertahankan objek itu, dan mungkin sudah ada objek dengan kunci utama yang sama yang terkait dengan sesi.

Contoh

Dengan asumsi Anda memiliki objek kelas hibernasi untuk tabel dengan 10 baris berdasarkan kombinasi kunci primer (kolom 1 dan kolom 2). Sekarang, Anda telah menghapus 5 baris dari tabel di beberapa titik waktu. Sekarang, jika Anda mencoba menambahkan 10 baris yang sama lagi, saat hibernate mencoba mempertahankan objek dalam database, 5 baris yang telah dihapus akan ditambahkan tanpa kesalahan. Sekarang 5 baris tersisa yang sudah ada, akan membuang pengecualian ini.

Jadi pendekatan yang mudah akan memeriksa apakah Anda telah memperbarui / menghapus nilai apa pun dalam tabel yang merupakan bagian dari sesuatu dan kemudian Anda mencoba memasukkan objek yang sama lagi

Michael Wiles
sumber
4
Jawaban Bagus². Kunci utama adalah masalah saya, diselesaikan dengan GeneratedValue mengatur urutan untuk postgresql.
Rodrigo Ferrari
2
Saya memiliki masalah yang sama. Dalam kasus saya, saya memiliki objek yang dicari dalam kode dan saya mencoba membuat objek baru dengan ID yang sama di bagian kode lain sementara objek pertama berada di sesi hibernate.
dellasavia
18

Ini hanya satu titik di mana hibernasi membuat lebih banyak masalah daripada menyelesaikannya. Dalam kasus saya, ada banyak objek dengan pengenal 0 yang sama, karena mereka baru dan belum memilikinya. DB menghasilkannya. Di suatu tempat saya telah membaca bahwa 0 sinyal Id tidak diatur. Cara intuitif untuk menahannya adalah mengulanginya dan mengucapkan hibernasi untuk menyimpan objek. Tetapi Anda tidak dapat melakukan itu - "Tentu saja Anda harus tahu bahwa hibernasi berfungsi ini dan itu, oleh karena itu Anda harus .." Jadi sekarang saya dapat mencoba mengubah Id menjadi Panjang daripada panjang dan melihat apakah kemudian berfungsi. Pada akhirnya, akan lebih mudah melakukannya dengan mapper sederhana sendiri, karena hibernasi hanyalah beban tambahan yang tidak transparan. Contoh lain: Mencoba membaca parameter dari satu database dan menyimpannya di database lain memaksa Anda untuk melakukan hampir semua pekerjaan secara manual.

Hein
sumber
13
Saya juga benci hibernasi ... dan database ... Setelah semua masalah yang mereka timbulkan kepada saya, saya kira lebih mudah menggunakan file teks (saya bercanda, tapi tetap saja ...).
Igor Popov
Dalam kasus saya, ada banyak objek dengan pengenal 0 yang sama, karena mereka baru dan belum memilikinya. DB menghasilkannya. Di suatu tempat saya telah membaca bahwa 0 sinyal Id tidak diatur. Cara intuitif untuk menahannya adalah mengulanginya dan mengucapkan hibernasi untuk menyimpan objek . Saya perlu melakukan ini. Bisakah Anda memberi tahu saya yang merupakan "cara hibernasi" untuk melakukan ini?
Ramses
Dalam kasus saya, saya harus menggunakan session.merge (myobject) karena saya memiliki dua contoh objek ini. Biasanya itu terjadi ketika entitas bertahan dan terlepas dari sesi. Contoh lain dari entitas ini diminta untuk hibernasi. Contoh kedua ini tetap melekat pada sesi. Contoh pertama diubah. Selengkapnya di getj2ee.over-blog.com/…
Reddymails
ini bukan masalah pembuatan hibernasi, tetapi kurangnya pemahaman tentang cara kerjanya
ACV
17

USe session.evict(object);Fungsi evict()metode digunakan untuk menghapus instance dari cache sesi. Jadi untuk pertama kalinya menyimpan objek, simpan objek dengan memanggilsession.save(object) metode sebelum mengeluarkan objek dari cache. Dengan cara yang sama, perbarui objek dengan memanggil session.saveOrUpdate(object)atau session.update(object)sebelum memanggil evict ().

Rahul N
sumber
11

Ini bisa terjadi ketika Anda telah menggunakan objek sesi yang sama untuk membaca & menulis. Bagaimana? Katakanlah Anda telah membuat satu sesi. Anda membaca catatan dari tabel karyawan dengan kunci utama Emp_id = 101 Sekarang Anda telah mengubah catatan di Java. Dan Anda akan menyimpan catatan Karyawan di database. kami belum menutup sesi di mana pun di sini. Sebagai objek yang dibaca juga bertahan dalam sesi tersebut. Ini bertentangan dengan objek yang ingin kita tulis. Karenanya kesalahan ini datang.

Prashant Bari
sumber
9

Seperti seseorang yang sudah ditunjukkan di atas, saya mengalami masalah ini ketika saya memiliki cascade=allkedua ujung one-to-manyhubungan, jadi mari kita asumsikan A -> B (satu-ke-banyak dari A dan banyak-ke-satu dari B) dan memperbarui contoh dari B di A dan kemudian memanggil saveOrUpdate (A), itu menghasilkan permintaan penyimpanan melingkar yaitu penyimpanan pemicu A, simpan B yang memicu penyimpanan A ... dan dalam contoh ketiga ketika entitas (dari A) dicoba untuk ditambahkan ke sessionPersistenceContext pengecualian duplikatObject dilemparkan.
  Saya bisa mengatasinya dengan menghapus kaskade dari satu ujung.

redzedi
sumber
Memecahkan masalah saya bersama dengan stackoverflow.com/questions/4334970/…
Magno C
5

Anda dapat menggunakan session.merge(obj), jika Anda melakukan penyimpanan dengan sesi yang berbeda dengan objek persisten pengenal yang sama.
Berhasil, saya memiliki masalah yang sama sebelumnya.

Pavan Kumar
sumber
4

Saya juga mengalami masalah ini dan kesulitan menemukan kesalahannya.

Masalah yang saya miliki adalah sebagai berikut:

Objek telah dibaca oleh Dao dengan sesi hibernasi yang berbeda.

Untuk menghindari pengecualian ini, cukup baca ulang objek dengan dao yang akan menyimpan / memperbarui objek ini nanti.

begitu:

class A{      

 readFoo(){
       someDaoA.read(myBadAssObject); //Different Session than in class B
    }

}

class B{



 saveFoo(){
       someDaoB.read(myBadAssObjectAgain); //Different Session than in class A
       [...]
       myBadAssObjectAgain.fooValue = 'bar';
       persist();
    }

}

Berharap bisa menghemat banyak waktu!

Frithjof
sumber
4

Saya mengalami masalah ini dengan:

  1. Menghapus objek (menggunakan HQL)
  2. Segera menyimpan objek baru dengan id yang sama

Saya menyelesaikannya dengan membersihkan hasil setelah menghapus, dan membersihkan cache sebelum menyimpan objek baru

String delQuery = "DELETE FROM OasisNode";
session.createQuery( delQuery ).executeUpdate();
session.flush();
session.clear();
wbdarby.dll
sumber
4

Masalah ini terjadi ketika kita memperbarui objek sesi yang sama, yang telah kita gunakan untuk mengambil objek dari database.

Anda dapat menggunakan metode gabungan hibernasi daripada metode pembaruan.

misalnya Pertama gunakan session.get () dan kemudian Anda bisa menggunakan session.merge (object). Cara ini tidak akan menimbulkan masalah. Kita juga bisa menggunakan metode merge () untuk memperbarui objek dalam database.

Jayendra Birtharia
sumber
3

Dapatkan objek di dalam sesi, berikut contohnya:

MyObject ob = null;
ob = (MyObject) session.get(MyObject.class, id);
sock_osg
sumber
3
Usaha yang bagus, tetapi objek "ob" dikembalikan tanpa data yang diperbarui (mengingat bahwa itu telah diperbarui melalui aplikasi selama runtime, antara objek yang mengambil dari database dan penyimpanannya).
Alex
2

Apakah pemetaan Id Anda benar? Jika database bertanggung jawab untuk membuat Id melalui pengenal, Anda perlu memetakan objek pengguna Anda ke itu ..

cwap
sumber
2

Saya mengalami masalah ini saat menghapus objek, baik evict maupun clear tidak membantu.

/**
 * Deletes the given entity, even if hibernate has an old reference to it.
 * If the entity has already disappeared due to a db cascade then noop.
 */
public void delete(final Object entity) {
  Object merged = null;
  try {
    merged = getSession().merge(entity);
  }
  catch (ObjectNotFoundException e) {
    // disappeared already due to cascade
    return;
  }
  getSession().delete(merged);
}
TimP
sumber
2

sebelum posisi di mana objek berulang dimulai, Anda harus menutup sesi dan kemudian Anda harus memulai sesi baru

session.close();      
session = HibernateUtil.getSessionFactory().openSession();

jadi dengan cara ini dalam satu sesi tidak lebih dari satu entitas yang memiliki identifier yang sama.

engtuncay
sumber
2

Terlambat ke pesta, tetapi mungkin membantu untuk pengguna yang akan datang -

Saya mendapat masalah ini ketika saya memilih catatan menggunakan getsession() dan sekali lagi memperbarui catatan lain dengan pengenal yang sama menggunakan sesi yang sama menyebabkan masalah. Kode ditambahkan di bawah.

Customer existingCustomer=getSession().get(Customer.class,1);
Customer customerFromUi;// This customer details comiong from UI with identifer 1

getSession().update(customerFromUi);// Here the issue comes

Ini tidak boleh dilakukan. Solusi adalah sesi penggusuran sebelum memperbarui atau mengubah logika bisnis.

vipin cp
sumber
1

Periksa apakah Anda lupa meletakkan @GenerateValue untuk kolom @Id. Saya memiliki masalah yang sama dengan banyak ke banyak hubungan antara Film dan Genre. Program melemparkan Kesalahan Hibernate: org.hibernate.NonUniqueObjectException: objek berbeda dengan nilai pengenal yang sama sudah terkait dengan kesalahan sesi. Saya kemudian mengetahui bahwa saya hanya perlu memastikan Anda memiliki @GenerateValue ke metode get GenreId.

Thupten
sumber
bagaimana cara menerapkan solusi Anda untuk pertanyaan saya? cara membuat kolom id di kelas Tugas? stackoverflow.com/questions/55732955/…
sbattou
1

cukup periksa id apakah dibutuhkan null atau 0 like

if(offersubformtwo.getId()!=null && offersubformtwo.getId()!=0)

di tambah atau perbarui di mana konten diatur dari formulir ke Pojo

Ayan Sarkar
sumber
1

Saya baru mengenal NHibernate, dan masalah saya adalah saya menggunakan sesi yang berbeda untuk menanyakan objek saya daripada yang saya lakukan untuk menyimpannya. Jadi sesi penyimpanan tidak tahu tentang objeknya.

Tampaknya jelas, tetapi dari membaca jawaban sebelumnya saya mencari 2 objek, bukan 2 sesi.

DustinA
sumber
1

@GeneratedValue (strategy = GenerationType.IDENTITY), menambahkan anotasi ini ke properti kunci utama di kacang entitas Anda harus menyelesaikan masalah ini.

Jay
sumber
1

Saya menyelesaikan masalah ini.
Sebenarnya ini terjadi karena kita lupa implementasi Jenis Generator properti PK di kelas kacang. Jadi buatlah semua jenis seperti

@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;

ketika kita mempertahankan objek kacang, setiap objek memperoleh ID yang sama, jadi objek pertama disimpan, ketika objek lain akan bertahan maka HIB FW melalui jenis Exception: org.hibernate.NonUniqueObjectException:objek yang berbeda dengan nilai pengenal yang sama sudah dikaitkan dengan sesi.

Ankit Sharma
sumber
1

Masalahnya terjadi karena dalam sesi hibernasi yang sama Anda mencoba menyimpan dua objek dengan pengenal yang sama. Ada dua solusi: -

  1. Ini terjadi karena Anda belum mengonfigurasi file mapping.xml dengan benar untuk bidang id seperti di bawah ini: -

    <id name="id">
      <column name="id" sql-type="bigint" not-null="true"/>
      <generator class="hibernateGeneratorClass"</generator>
    </id>
  2. Overload metode getsession untuk menerima Parameter seperti isSessionClear, dan hapus sesi sebelum mengembalikan sesi saat ini seperti di bawah

    public static Session getSession(boolean isSessionClear) {
        if (session.isOpen() && isSessionClear) {
            session.clear();
            return session;
        } else if (session.isOpen()) {
            return session;
        } else {
            return sessionFactory.openSession();
        }
    }

Ini akan menyebabkan objek sesi yang ada dihapus dan bahkan jika hibernasi tidak menghasilkan pengenal unik, dengan asumsi Anda telah mengkonfigurasi database Anda dengan benar untuk kunci utama menggunakan sesuatu seperti Auto_Increment, itu akan bekerja untuk Anda.

Rahul Kumar
sumber
1

Saya memiliki masalah serupa. Dalam kasus saya, saya lupa mengatur increment_bynilai dalam database agar sama seperti yang digunakan oleh cache_sizedan allocationSize. (Panah menunjuk ke atribut yang disebutkan)

SQL:

CREATED         26.07.16
LAST_DDL_TIME   26.07.16
SEQUENCE_OWNER  MY
SEQUENCE_NAME   MY_ID_SEQ
MIN_VALUE       1
MAX_VALUE       9999999999999999999999999999
INCREMENT_BY    20 <-
CYCLE_FLAG      N
ORDER_FLAG      N
CACHE_SIZE      20 <-
LAST_NUMBER     180

Jawa:

@SequenceGenerator(name = "mySG", schema = "my", 
sequenceName = "my_id_seq", allocationSize = 20 <-)
kaba713
sumber
1

Selain dari apa yang dikatakan wbdarby , itu bahkan bisa terjadi ketika sebuah objek diambil dengan memberikan pengidentifikasi objek ke HQL. Dalam kasus mencoba untuk mengubah bidang objek dan menyimpannya kembali ke dalam DB (modifikasi dapat dimasukkan, dihapus atau diperbarui) pada sesi yang sama , kesalahan ini akan muncul. Coba bersihkan sesi hibernasi sebelum menyimpan objek yang dimodifikasi atau buat sesi baru.

Harap saya membantu ;-)

Arash moradabadi
sumber
1

Saya memiliki kesalahan yang sama saya mengganti Set saya dengan yang baru dari Jackson.

Untuk mengatasi ini saya menyimpan set yang ada, saya menghapus dari set lama elemen yang tidak diketahui ke dalam daftar baru retainAll. Lalu saya menambahkan yang baru dengan addAll.

    this.oldSet.retainAll(newSet);
    this.oldSet.addAll(newSet);

Tidak perlu memiliki Sesi dan memanipulasinya.

Ôrel
sumber
1

Coba ini. Di bawah ini berhasil untuk saya!

Di dalam hbm.xmlfile

  1. Kita perlu mengatur dynamic-updateatribut tag kelas ke true:

    <class dynamic-update="true">
  2. Setel atribut kelas dari tag generator di bawah kolom unik ke identity:

    <generator class="identity">

Catatan: Tetapkan kolom unik ke identitydaripada assigned.

RaGa__M
sumber
0

Hal lain yang berhasil bagi saya adalah membuat variabel instance Long menggantikan long


Saya memiliki id panjang variabel kunci utama saya; mengubahnya menjadi Long id; bekerja

Semua yang terbaik


sumber
0

Anda selalu bisa melakukan sesi flush. Flush akan menyinkronkan status semua objek Anda dalam sesi (tolong, seseorang mengoreksi saya jika saya salah), dan mungkin itu akan menyelesaikan masalah Anda dalam beberapa kasus.

Menerapkan persamaan dan kode hash Anda sendiri dapat membantu Anda juga.

caarlos0
sumber
0

Anda dapat memeriksa Pengaturan Kaskade Anda. Pengaturan Cascade pada model Anda dapat menyebabkan hal ini. Saya menghapus Pengaturan Kaskade (Pada dasarnya tidak mengizinkan Sisipan / Pembaruan Kaskade) dan ini memecahkan masalah saya

pengguna1609848
sumber
0

Saya menemukan kesalahan ini juga. Apa yang berhasil bagi saya adalah memastikan bahwa kunci utama (yang dihasilkan secara otomatis) bukan PDT (yaitu panjang, int, dll.), Tetapi sebuah objek (yaitu Panjang, Integer, dll.)

Saat Anda membuat objek untuk menyimpannya, pastikan Anda mengirimkan null dan bukan 0.

Jaco Van Niekerk
sumber
0

Apakah ini membantu?

User userObj1 = new User();
User userObj2 = userObj1;
.
.
.
rtsession.save(userObj1);
rtsession.save(userObj2); 
George Papatheodorou
sumber
0

Saya telah memecahkan masalah serupa seperti itu:

plan = (FcsRequestPlan) session.load(plan.getClass(), plan.getUUID());
while (plan instanceof HibernateProxy)
    plan = (FcsRequestPlan) ((HibernateProxy) plan).getHibernateLazyInitializer().getImplementation();
pengguna3132194
sumber