Dalam konteks kekurangan adalah kesalahan ini? apakah dengan atau tanpa variabel sementara?
vijay
Jawaban:
803
Anda harus memasukkan cascade="all"(jika menggunakan xml) atau cascade=CascadeType.ALL(jika menggunakan anotasi) pada pemetaan koleksi Anda.
Ini terjadi karena Anda memiliki koleksi di entitas Anda, dan koleksi itu memiliki satu atau lebih item yang tidak ada dalam database. Dengan menentukan opsi di atas, Anda memberi tahu hibernate untuk menyimpannya ke basis data saat menyimpan induknya.
Bukankah ini implisit? Tidakkah Anda selalu ingin Hibernate menyimpannya?
Marcus Leon
29
@ Marscus - tidak, tidak. Anda mungkin ingin menanganinya secara manual.
Bozho
5
Bozho benar. Saya telah mengalami keadaan di mana saya memiliki koleksi yang ingin saya kelola secara manual karena ukurannya, atau karena aturan bisnis yang tidak mengizinkan semua objek dalam koleksi disimpan pada saat yang sama.
Alex Marshall
26
Itu tidak hanya terjadi pada koleksi tetapi juga pemetaan satu-ke-satu
Sebastien Lorber
12
Bukankah lebih baik memulai dengan CascadeType.PERSIST dan menggunakan bertahan untuk menyimpan?
Sergii Shevchyk
248
Saya percaya ini mungkin hanya jawaban berulang, tetapi hanya untuk memperjelas, saya mendapatkan ini pada @OneToOnepemetaan dan juga @OneToMany. Dalam kedua kasus, itu adalah fakta bahwa Childobjek yang saya tambahkan ke Parentbelum disimpan dalam database. Jadi ketika saya menambahkan Childke Parent, lalu menyimpan Parent, Hibernate akan melemparkan "object references an unsaved transient instance - save the transient instance before flushing"pesan saat menyimpan Induk.
Menambahkan di cascade = {CascadeType.ALL}atas Parent'smengacu pada Childmemecahkan masalah dalam kedua kasus. Ini menyelamatkan Childdan Parent.
Maaf atas jawaban berulang, hanya ingin menjelaskan lebih lanjut untuk orang-orang.
Bagaimana jika saya tidak ingin menyimpan simpanan pada hubungan @OneToOne? Saat membuat kedua objek untuk pertama kalinya, bagaimana saya bisa menyimpan ke database tanpa memicu pengecualian?
xtian
4
Bagaimana jika saya ingin menyelamatkan anak untuk beberapa kasus dan bukan untuk yang lain?
Omaruchan
@xtian: Baiklah Anda harus menjaga urutan penyimpanan yang benar ke database dengan tetap menggunakan objek dengan EntityManager. Pada dasarnya Anda hanya mengatakan em.persist (object1); em.persist (object2); dll.
kaba713
Saya mendapatkan masalah ini secara khusus ketika saya menggunakan @Inheritance, dalam hal ini TABLE_PER_CLASS, saya mereferensikan sebuah subclass. CascadeType.ALL memperbaikinya.
Jim ReesPotter
Atau Anda telah membuat objek entitas Anda dengan new MyEntity(tanpa menyinkronkannya ke database - pembilasan), alih-alih mendapatkan instance yang disinkronkan dari database. Membuat pertanyaan Hibernate menggunakan instance itu memberi tahu Anda bahwa apa yang Anda harapkan berada dalam database berbeda dari apa yang Anda miliki dalam memori aplikasi Anda. Dalam hal ini - cukup menyinkronkan / mendapatkan instabnce entitas Anda dari DB dan menggunakannya. Tidak perlu CascadeType.ALL.
Zon
67
Ini terjadi saat menyimpan objek ketika Hibernate merasa perlu menyimpan objek yang dikaitkan dengan objek yang Anda simpan.
Saya punya masalah ini dan tidak ingin menyimpan perubahan ke objek yang direferensikan jadi saya ingin jenis kaskade menjadi NONE.
Caranya adalah memastikan bahwa ID dan VERSION dalam objek yang direferensikan diatur sehingga Hibernate tidak berpikir bahwa objek yang direferensikan adalah objek baru yang perlu disimpan. Ini berhasil untuk saya.
Lihat semua hubungan dalam kelas yang Anda simpan untuk mengetahui objek terkait (dan objek terkait dari objek terkait) dan memastikan bahwa ID dan VERSI diatur di semua objek dari pohon objek.
Komentar ini menempatkan saya di jalur yang benar. Saya menugaskan contoh baru dari orang tua ke properti anaknya. Jadi NH berpikir mereka berbeda.
elvin
2
Iya. Ini terjadi jika, misalnya, id dari objek terkait tidak disertakan (misalnya, diabaikan oleh @JsonIgnore). Hibernate tidak memiliki cara mengidentifikasi entitas terkait, jadi ia ingin menyimpannya.
Rori Stumpf
36
pengantar
Seperti yang saya jelaskan dalam artikel ini saat menggunakan JPA dan Hibernate, sebuah entitas dapat berada di salah satu dari 4 negara berikut:
Baru - Objek yang baru dibuat yang belum pernah dikaitkan dengan Hibernate Session (alias Persistence Context) dan tidak dipetakan ke baris tabel basis data apa pun yang dianggap berada dalam keadaan Baru atau Transien.
Untuk bertahan, kita perlu secara eksplisit memanggil persistmetode atau memanfaatkan mekanisme kegigihan transitif.
Persistent - Entitas persisten telah dikaitkan dengan baris tabel database dan dikelola oleh Konteks Persistence yang sedang berjalan.
Setiap perubahan yang dibuat untuk entitas seperti itu akan dideteksi dan disebarkan ke database (selama Sesi flush-time).
Terpisah - Setelah Persistence Konteks yang sedang berjalan ditutup, semua entitas yang sebelumnya dikelola menjadi terpisah. Perubahan yang berurutan tidak akan lagi dilacak dan tidak ada sinkronisasi basis data otomatis yang akan terjadi.
Dihapus - Meskipun JPA menuntut agar entitas yang dikelola hanya diizinkan untuk dihapus, Hibernate juga dapat menghapus entitas yang terpisah (tetapi hanya melalui removepemanggilan metode).
Transisi status entitas
Untuk memindahkan entitas dari satu status ke kondisi lainnya, Anda dapat menggunakan persist, removeatau mergemetode.
Memperbaiki masalah
Masalah yang Anda uraikan dalam pertanyaan Anda:
object references an unsaved transient instance - save the transient instance before flushing
disebabkan oleh mengaitkan entitas di negara bagian Baru ke entitas yang ada di negara bagian yang Dikelola .
Ini bisa terjadi ketika Anda mengasosiasikan entitas anak ke koleksi satu-ke-banyak di entitas induk, dan koleksi tersebut tidak cascadetransisi status entitas entitas.
Jadi, seperti yang saya jelaskan di artikel ini , Anda bisa memperbaikinya dengan menambahkan kaskade ke asosiasi entitas yang memicu kegagalan ini, sebagai berikut:
Dalam sebuah @ManyToManyasosiasi, Anda tidak dapat menggunakan CascadeType.ALLatau orphanRemovalkarena ini akan menyebarkan transisi status entitas hapus dari satu induk ke entitas induk lainnya.
Oleh karena itu, untuk @ManyToManyasosiasi, Anda biasanya melakukan kaskade CascadeType.PERSISTatau CascadeType.MERGEoperasi. Atau, Anda dapat memperluas itu ke DETACHatau REFRESH.
Untuk detail lebih lanjut tentang cara terbaik untuk memetakan @ManyToManyasosiasi, lihat artikel ini juga.
Ini harus menjadi jawaban yang diterima. CascadeType.ALL terlalu luas
lilalinux
5
Pada Hibernate 5.2.8, sepertinya tidak ada cara untuk mencapai efek yang sama dengan penjelasan JPA. Misalnya, @ManyToMany(cascade={PERSIST, MERGE, REFRESH, DETACH})(semua kecuali HAPUS) tidak membuat pembaruan seperti yang dilakukan Hibernate CascadeType.SAVE_UPDATE.
jcsahnwaldt mengatakan GoFundMonica
25
Dalam kasus saya itu disebabkan oleh tidak memiliki CascadeTypedi @ManyToOnesisi hubungan dua arah. Untuk lebih tepat, aku punya CascadeType.ALLdi @OneToManysisi dan tidak memiliki itu @ManyToOne. Menambahkan CascadeType.ALLuntuk @ManyToOnemenyelesaikan masalah.
Satu-ke-banyak sisi:
Jika saya melakukannya dengan cara ini, dan menyimpan entitas induk, yang terjadi adalah ada dua sisipan di tabel induk saya yaitu dua baris. Saya pikir ini karena kita memiliki kaskade pada entitas induk dan anak?
Pemrogram
18
Ini terjadi bagi saya ketika mempertahankan entitas di mana catatan yang ada di database memiliki nilai NULL untuk bidang yang dianotasi dengan @Version (untuk penguncian optimis). Memperbarui nilai NULL ke 0 dalam basis data mengoreksi ini.
Ini harus menjadi pertanyaan baru dan harus ditambahkan sebagai bug, setidaknya pengecualian yang menyesatkan. Ini ternyata menjadi penyebab masalah saya.
BML
Ini memperbaiki masalah saya
Jad Chahine
11
Ini bukan satu-satunya alasan untuk kesalahan ini. Saya baru saja menemukannya untuk kesalahan ketik dalam pengkodean saya, yang saya percaya, menetapkan nilai entitas yang sudah disimpan.
X x2 =new X();
x.setXid(memberid);// Error happened here - x was a previous global entity I created earlier
Y.setX(x2);
Saya melihat kesalahan dengan menemukan variabel mana yang menyebabkan kesalahan (dalam hal ini String xid). Saya menggunakan catchsekitar seluruh blok kode yang menyelamatkan entitas dan mencetak jejak.
{
code block that performed the operation
}catch(Exception e){
e.printStackTrace();// put a break-point here and inspect the 'e'return ERROR;}
Masalah serupa dengan saya. Lagi pula, ketika saya memuat kembali entitas secara lokal, mengatur properti, lalu menyimpan, itu berfungsi dengan baik.
CsBalazsHungary
8
Jangan gunakan Cascade.Allsampai Anda benar-benar harus melakukannya. Roledan Permissionmemiliki manyToManyhubungan dua arah . Kemudian kode berikut akan berfungsi dengan baik
Permission p =newPermission();
p.setName("help");Permission p2 =newPermission();
p2.setName("self_info");
p =(Permission)crudRepository.save(p);// returned p has id filled in.
p2 =(Permission)crudRepository.save(p2);// so does p2.Role role =newRole();
role.setAvailable(true);
role.setDescription("a test role");
role.setRole("admin");List<Permission> pList =newArrayList<Permission>();
pList.add(p);
pList.add(p2);
role.setPermissions(pList);
crudRepository.save(role);
sementara jika objek hanya "baru", maka itu akan melempar kesalahan yang sama.
100% benar, Cascade.All adalah solusi malas dan hanya harus diterapkan saat diperlukan. pertama, jika entitas sudah ada, periksa apakah sudah dimuat di manajer entitas saat ini, jika tidak memuatnya.
Renato Mendes
7
Jika koleksi Anda tidak dapat dibatalkan, cobalah: object.SetYouColection(null);
Ini benar-benar masalah saya. Saya tidak akan pernah menduga saya harus secara manual mengaturnya ke nol.
Deadron
Ini juga masalah saya. Saya tidak menggunakan koleksi, jadi saya tidak mencoba ini pada awalnya, tapi saya mengatur objek saya ke nol dan sekarang berfungsi.
Makanan ternak
5
Untuk menambahkan 2 sen, saya mendapatkan masalah yang sama ketika saya secara tidak sengaja mengirim nullsebagai ID. Kode di bawah ini menggambarkan skenario saya (dan OP tidak menyebutkan skenario spesifik) .
Employee emp =newEmployee();
emp.setDept(newDept(deptId));// --> when deptId PKID is null, same error will be thrown// calls to other setters...
em.persist(emp);
Di sini saya mengatur id departemen yang ada ke instance karyawan baru tanpa benar-benar mendapatkan entitas departemen terlebih dahulu, karena saya tidak ingin memunculkan kueri pemilihan lain.
Dalam beberapa skenario, deptIdPKID berasal nulldari metode panggilan dan saya mendapatkan kesalahan yang sama.
Saya punya masalah serupa. Saya mendapatkan pengecualian ketika deptID saya adalah 0. Nilai lain yang lebih besar dari 0 berfungsi. Lucu adalah bahwa saya memiliki dept dengan id = 0.
Gustavo
5
Masalah ini terjadi pada saya ketika saya membuat entitas baru dan entitas terkait dalam metode yang ditandai sebagai @Transactional, lalu melakukan kueri sebelum menyimpan. Ex
@Transactionalpublic someService(){Entity someEntity =newEntity();AssocaiatedEntity associatedEntity =newAssocaitedEntity();
someEntity.setAssociatedEntity(associatedEntity);
associatedEntity.setEntity(someEntity);// Performing any query was causing hibernate to attempt to persist the new entity. It would then throw an exception
someDao.getSomething();
entityDao.create(someEntity);}
Untuk memperbaikinya, saya melakukan kueri sebelum membuat entitas baru.
di samping semua jawaban baik lainnya, ini bisa terjadi jika Anda menggunakan mergeuntuk bertahan suatu objek dan secara tidak sengaja lupa untuk menggunakan referensi objek yang digabung dalam kelas induk. pertimbangkan contoh berikut
merge(A);
B.setA(A);
persist(B);
Dalam kasus ini, Anda menggabungkan Atetapi lupa untuk menggunakan objek gabungan A. untuk menyelesaikan masalah Anda harus menulis ulang kode seperti ini.
A=merge(A);//difference is here
B.setA(A);
persist(B);
Saya juga menghadapi situasi yang sama. Dengan mengatur anotasi berikut di atas properti membuatnya menyelesaikan pengecualian yang diminta.
Pengecualian yang saya hadapi.
Exception in thread "main" java.lang.IllegalStateException: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.model.Car_OneToMany
Metode setNewPassword () membuat catatan PasswordHistory dan menambahkannya ke koleksi sejarah di Pengguna. Karena pernyataan create () belum dieksekusi untuk induk, itu mencoba menyimpan ke koleksi entitas yang belum dibuat. Yang harus saya lakukan untuk memperbaikinya adalah memindahkan panggilan setNewPassword () setelah panggilan untuk membuat ().
Ada kemungkinan lain yang dapat menyebabkan kesalahan ini dalam hibernasi. Anda dapat menetapkan referensi yang belum disimpan dari objek Anda Ake entitas terlampir Bdan ingin tetap objek C. Bahkan dalam kasus ini, Anda akan mendapatkan kesalahan yang disebutkan di atas.
Saya pikir itu karena Anda telah mencoba untuk bertahan objek yang memiliki referensi ke objek lain yang belum bertahan, dan itu mencoba di "sisi DB" untuk menempatkan referensi ke baris yang tidak ada
Cara sederhana untuk memecahkan masalah ini adalah menyelamatkan kedua entitas. pertama simpan entitas anak dan kemudian simpan entitas induk. Karena entitas induk bergantung pada entitas anak untuk nilai kunci asing.
Di bawah ini ujian sederhana hubungan satu lawan satu
insert into Department(name, numOfemp,Depno) values (?,?,?)Hibernate: insert into Employee(SSN, dep_Depno, firstName, lastName, middleName, empno) values (?,?,?,?,?,?)Session session=sf.openSession();
session.beginTransaction();
session.save(dep);
session.save(emp);
Sebaliknya - entitas anak memegang nilai FK dan bergantung pada orang tua sehingga Anda harus menyelamatkan orang tua terlebih dahulu! Di blok kode Anda sudah benar.
17ber
0
Salah satu kemungkinan penyebab kesalahan adalah tidak adanya pengaturan nilai entitas induk; misalnya untuk hubungan departemen-karyawan Anda harus menulis ini untuk memperbaiki kesalahan:
Department dept =(Department)session.load(Department.class, dept_code);// dept_code is from the jsp form which you get in the controller with @RequestParam String department
employee.setDepartment(dept);
Ada begitu banyak kemungkinan kesalahan ini, beberapa kemungkinan lain juga ada di halaman tambah atau edit. Dalam kasus saya, saya mencoba untuk menyimpan objek AdvanceSalary. Masalahnya adalah bahwa dalam pengeditan AdvanceSalary employee.employee_id adalah null Karena pada pengeditan saya tidak menetapkan employee.employee_id. Saya telah membuat bidang tersembunyi dan mengaturnya. kode saya bekerja dengan sangat baik.
Saya menghadapi pengecualian ini ketika saya tidak bertahan pada objek orang tua tetapi saya menyelamatkan anak itu. Untuk mengatasi masalah ini, dengan di sesi yang sama saya bertahan objek anak dan orang tua dan menggunakan CascadeType.ALL pada orang tua.
Kasus 1: Saya mendapatkan pengecualian ini ketika saya mencoba membuat orangtua dan menyimpan referensi orangtua itu untuk anaknya dan kemudian beberapa DELETE / UPDATE query (JPQL) lainnya. Jadi saya hanya flush () entitas yang baru dibuat setelah membuat induk dan setelah membuat anak menggunakan referensi induk yang sama. Ini berhasil untuk saya.
Dalam kasus di atas di mana induk (Referensi) dan anak (ReferenceAdditionalDetails) memiliki hubungan OneToOne dan ketika Anda mencoba membuat entitas Referensi dan kemudian anaknya (ReferenceAdditionalDetails), itu akan memberi Anda pengecualian yang sama. Jadi untuk menghindari pengecualian Anda harus menetapkan nol untuk kelas anak dan kemudian membuat induknya. (Contoh Kode)
Masalah saya terkait dengan @BeforeEachJUnit. Dan bahkan jika saya menyimpan entitas terkait (dalam kasus saya @ManyToOne), saya mendapatkan kesalahan yang sama.
Masalahnya entah bagaimana terkait dengan urutan yang saya miliki di orang tua saya. Jika saya menetapkan nilai ke atribut itu, masalahnya terpecahkan.
Ex. Jika saya memiliki Pertanyaan entitas yang dapat memiliki beberapa kategori (satu atau lebih) dan Pertanyaan entitas memiliki urutan:
Buat Constructor pemetaan Anda di kelas dasar Anda. Seperti jika Anda ingin hubungan One-To-One di Entity A, Entity B. jika Anda mengambil A sebagai kelas dasar, maka A harus memiliki Konstruktor memiliki B sebagai argumen.
Jawaban:
Anda harus memasukkan
cascade="all"
(jika menggunakan xml) ataucascade=CascadeType.ALL
(jika menggunakan anotasi) pada pemetaan koleksi Anda.Ini terjadi karena Anda memiliki koleksi di entitas Anda, dan koleksi itu memiliki satu atau lebih item yang tidak ada dalam database. Dengan menentukan opsi di atas, Anda memberi tahu hibernate untuk menyimpannya ke basis data saat menyimpan induknya.
sumber
Saya percaya ini mungkin hanya jawaban berulang, tetapi hanya untuk memperjelas, saya mendapatkan ini pada
@OneToOne
pemetaan dan juga@OneToMany
. Dalam kedua kasus, itu adalah fakta bahwaChild
objek yang saya tambahkan keParent
belum disimpan dalam database. Jadi ketika saya menambahkanChild
keParent
, lalu menyimpanParent
, Hibernate akan melemparkan"object references an unsaved transient instance - save the transient instance before flushing"
pesan saat menyimpan Induk.Menambahkan di
cascade = {CascadeType.ALL}
atasParent's
mengacu padaChild
memecahkan masalah dalam kedua kasus. Ini menyelamatkanChild
danParent
.Maaf atas jawaban berulang, hanya ingin menjelaskan lebih lanjut untuk orang-orang.
sumber
new MyEntity
(tanpa menyinkronkannya ke database - pembilasan), alih-alih mendapatkan instance yang disinkronkan dari database. Membuat pertanyaan Hibernate menggunakan instance itu memberi tahu Anda bahwa apa yang Anda harapkan berada dalam database berbeda dari apa yang Anda miliki dalam memori aplikasi Anda. Dalam hal ini - cukup menyinkronkan / mendapatkan instabnce entitas Anda dari DB dan menggunakannya. Tidak perlu CascadeType.ALL.Ini terjadi saat menyimpan objek ketika Hibernate merasa perlu menyimpan objek yang dikaitkan dengan objek yang Anda simpan.
Saya punya masalah ini dan tidak ingin menyimpan perubahan ke objek yang direferensikan jadi saya ingin jenis kaskade menjadi NONE.
Caranya adalah memastikan bahwa ID dan VERSION dalam objek yang direferensikan diatur sehingga Hibernate tidak berpikir bahwa objek yang direferensikan adalah objek baru yang perlu disimpan. Ini berhasil untuk saya.
Lihat semua hubungan dalam kelas yang Anda simpan untuk mengetahui objek terkait (dan objek terkait dari objek terkait) dan memastikan bahwa ID dan VERSI diatur di semua objek dari pohon objek.
sumber
pengantar
Seperti yang saya jelaskan dalam artikel ini saat menggunakan JPA dan Hibernate, sebuah entitas dapat berada di salah satu dari 4 negara berikut:
Baru - Objek yang baru dibuat yang belum pernah dikaitkan dengan Hibernate Session (alias Persistence Context) dan tidak dipetakan ke baris tabel basis data apa pun yang dianggap berada dalam keadaan Baru atau Transien.
Untuk bertahan, kita perlu secara eksplisit memanggil
persist
metode atau memanfaatkan mekanisme kegigihan transitif.Persistent - Entitas persisten telah dikaitkan dengan baris tabel database dan dikelola oleh Konteks Persistence yang sedang berjalan.
Setiap perubahan yang dibuat untuk entitas seperti itu akan dideteksi dan disebarkan ke database (selama Sesi flush-time).
Terpisah - Setelah Persistence Konteks yang sedang berjalan ditutup, semua entitas yang sebelumnya dikelola menjadi terpisah. Perubahan yang berurutan tidak akan lagi dilacak dan tidak ada sinkronisasi basis data otomatis yang akan terjadi.
Dihapus - Meskipun JPA menuntut agar entitas yang dikelola hanya diizinkan untuk dihapus, Hibernate juga dapat menghapus entitas yang terpisah (tetapi hanya melalui
remove
pemanggilan metode).Transisi status entitas
Untuk memindahkan entitas dari satu status ke kondisi lainnya, Anda dapat menggunakan
persist
,remove
ataumerge
metode.Memperbaiki masalah
Masalah yang Anda uraikan dalam pertanyaan Anda:
disebabkan oleh mengaitkan entitas di negara bagian Baru ke entitas yang ada di negara bagian yang Dikelola .
Ini bisa terjadi ketika Anda mengasosiasikan entitas anak ke koleksi satu-ke-banyak di entitas induk, dan koleksi tersebut tidak
cascade
transisi status entitas entitas.Jadi, seperti yang saya jelaskan di artikel ini , Anda bisa memperbaikinya dengan menambahkan kaskade ke asosiasi entitas yang memicu kegagalan ini, sebagai berikut:
The
@OneToOne
asosiasiThe
@OneToMany
asosiasiSekali lagi,
CascadeType.ALL
ini cocok untuk asosiasi dua arah@OneToMany
.Sekarang, agar kaskade berfungsi dengan baik dalam dua arah, Anda juga perlu memastikan bahwa asosiasi orang tua dan anak dalam sinkronisasi.
The
@ManyToMany
asosiasiDalam sebuah
@ManyToMany
asosiasi, Anda tidak dapat menggunakanCascadeType.ALL
atauorphanRemoval
karena ini akan menyebarkan transisi status entitas hapus dari satu induk ke entitas induk lainnya.Oleh karena itu, untuk
@ManyToMany
asosiasi, Anda biasanya melakukan kaskadeCascadeType.PERSIST
atauCascadeType.MERGE
operasi. Atau, Anda dapat memperluas itu keDETACH
atauREFRESH
.sumber
Atau, jika Anda ingin menggunakan "kekuatan" minimal (mis. Jika Anda tidak ingin penghapusan kaskade) untuk mencapai apa yang Anda inginkan, gunakan
sumber
@ManyToMany(cascade={PERSIST, MERGE, REFRESH, DETACH})
(semua kecuali HAPUS) tidak membuat pembaruan seperti yang dilakukan HibernateCascadeType.SAVE_UPDATE
.Dalam kasus saya itu disebabkan oleh tidak memiliki
CascadeType
di@ManyToOne
sisi hubungan dua arah. Untuk lebih tepat, aku punyaCascadeType.ALL
di@OneToMany
sisi dan tidak memiliki itu@ManyToOne
. MenambahkanCascadeType.ALL
untuk@ManyToOne
menyelesaikan masalah. Satu-ke-banyak sisi:Banyak-ke-satu sisi (menyebabkan masalah)
Banyak-ke-satu (diperbaiki dengan menambahkan
CascadeType.PERSIST
)sumber
Ini terjadi bagi saya ketika mempertahankan entitas di mana catatan yang ada di database memiliki nilai NULL untuk bidang yang dianotasi dengan @Version (untuk penguncian optimis). Memperbarui nilai NULL ke 0 dalam basis data mengoreksi ini.
sumber
Ini bukan satu-satunya alasan untuk kesalahan ini. Saya baru saja menemukannya untuk kesalahan ketik dalam pengkodean saya, yang saya percaya, menetapkan nilai entitas yang sudah disimpan.
Saya melihat kesalahan dengan menemukan variabel mana yang menyebabkan kesalahan (dalam hal ini
String xid
). Saya menggunakancatch
sekitar seluruh blok kode yang menyelamatkan entitas dan mencetak jejak.sumber
Jangan gunakan
Cascade.All
sampai Anda benar-benar harus melakukannya.Role
danPermission
memilikimanyToMany
hubungan dua arah . Kemudian kode berikut akan berfungsi dengan baiksementara jika objek hanya "baru", maka itu akan melempar kesalahan yang sama.
sumber
Jika koleksi Anda tidak dapat dibatalkan, cobalah:
object.SetYouColection(null);
sumber
Untuk menambahkan 2 sen, saya mendapatkan masalah yang sama ketika saya secara tidak sengaja mengirim
null
sebagai ID. Kode di bawah ini menggambarkan skenario saya (dan OP tidak menyebutkan skenario spesifik) .Di sini saya mengatur id departemen yang ada ke instance karyawan baru tanpa benar-benar mendapatkan entitas departemen terlebih dahulu, karena saya tidak ingin memunculkan kueri pemilihan lain.
Dalam beberapa skenario,
deptId
PKID berasalnull
dari metode panggilan dan saya mendapatkan kesalahan yang sama.Jadi, perhatikan
null
nilai untuk PK IDsumber
Masalah ini terjadi pada saya ketika saya membuat entitas baru dan entitas terkait dalam metode yang ditandai sebagai
@Transactional
, lalu melakukan kueri sebelum menyimpan. ExUntuk memperbaikinya, saya melakukan kueri sebelum membuat entitas baru.
sumber
di samping semua jawaban baik lainnya, ini bisa terjadi jika Anda menggunakan
merge
untuk bertahan suatu objek dan secara tidak sengaja lupa untuk menggunakan referensi objek yang digabung dalam kelas induk. pertimbangkan contoh berikutDalam kasus ini, Anda menggabungkan
A
tetapi lupa untuk menggunakan objek gabunganA
. untuk menyelesaikan masalah Anda harus menulis ulang kode seperti ini.sumber
saya mendapatkan kesalahan ini saat saya gunakan
tetapi berfungsi tanpa masalah saat saya gunakan
sumber
Saya juga menghadapi situasi yang sama. Dengan mengatur anotasi berikut di atas properti membuatnya menyelesaikan pengecualian yang diminta.
Pengecualian yang saya hadapi.
Untuk mengatasinya, anotasi yang saya gunakan.
Apa yang membuat Hibernate melempar pengecualian:
Pengecualian ini dilemparkan ke konsol Anda karena objek anak yang saya lampirkan ke objek induk tidak ada dalam database pada saat itu.
Dengan menyediakan
@OneToMany(cascade = {CascadeType.ALL})
, ini memberitahu Hibernate untuk menyimpannya ke database sambil menyimpan objek induk.sumber
Demi kelengkapan: A
dengan pesan
juga akan terjadi ketika Anda mencoba untuk bertahan / menggabungkan suatu entitas dengan referensi ke entitas lain yang kebetulan terlepas .
sumber
Satu alasan lain yang mungkin: dalam kasus saya, saya berusaha menyelamatkan anak sebelum menyelamatkan orang tua, pada entitas baru.
Kode itu seperti ini dalam model User.java:
Metode setNewPassword () membuat catatan PasswordHistory dan menambahkannya ke koleksi sejarah di Pengguna. Karena pernyataan create () belum dieksekusi untuk induk, itu mencoba menyimpan ke koleksi entitas yang belum dibuat. Yang harus saya lakukan untuk memperbaikinya adalah memindahkan panggilan setNewPassword () setelah panggilan untuk membuat ().
sumber
Ada kemungkinan lain yang dapat menyebabkan kesalahan ini dalam hibernasi. Anda dapat menetapkan referensi yang belum disimpan dari objek Anda
A
ke entitas terlampirB
dan ingin tetap objekC
. Bahkan dalam kasus ini, Anda akan mendapatkan kesalahan yang disebutkan di atas.sumber
Jika Anda menggunakan Spring Data JPA maka
@Transactional
anotasi tambahan untuk implementasi layanan Anda akan menyelesaikan masalah.sumber
Saya pikir itu karena Anda telah mencoba untuk bertahan objek yang memiliki referensi ke objek lain yang belum bertahan, dan itu mencoba di "sisi DB" untuk menempatkan referensi ke baris yang tidak ada
sumber
Cara sederhana untuk memecahkan masalah ini adalah menyelamatkan kedua entitas. pertama simpan entitas anak dan kemudian simpan entitas induk. Karena entitas induk bergantung pada entitas anak untuk nilai kunci asing.
Di bawah ini ujian sederhana hubungan satu lawan satu
sumber
Salah satu kemungkinan penyebab kesalahan adalah tidak adanya pengaturan nilai entitas induk; misalnya untuk hubungan departemen-karyawan Anda harus menulis ini untuk memperbaiki kesalahan:
sumber
Ada begitu banyak kemungkinan kesalahan ini, beberapa kemungkinan lain juga ada di halaman tambah atau edit. Dalam kasus saya, saya mencoba untuk menyimpan objek AdvanceSalary. Masalahnya adalah bahwa dalam pengeditan AdvanceSalary employee.employee_id adalah null Karena pada pengeditan saya tidak menetapkan employee.employee_id. Saya telah membuat bidang tersembunyi dan mengaturnya. kode saya bekerja dengan sangat baik.
sumber
Saya menghadapi pengecualian ini ketika saya tidak bertahan pada objek orang tua tetapi saya menyelamatkan anak itu. Untuk mengatasi masalah ini, dengan di sesi yang sama saya bertahan objek anak dan orang tua dan menggunakan CascadeType.ALL pada orang tua.
sumber
Kasus 1: Saya mendapatkan pengecualian ini ketika saya mencoba membuat orangtua dan menyimpan referensi orangtua itu untuk anaknya dan kemudian beberapa DELETE / UPDATE query (JPQL) lainnya. Jadi saya hanya flush () entitas yang baru dibuat setelah membuat induk dan setelah membuat anak menggunakan referensi induk yang sama. Ini berhasil untuk saya.
Kasus 2:
Kelas induk
Kelas Anak:
Dalam kasus di atas di mana induk (Referensi) dan anak (ReferenceAdditionalDetails) memiliki hubungan OneToOne dan ketika Anda mencoba membuat entitas Referensi dan kemudian anaknya (ReferenceAdditionalDetails), itu akan memberi Anda pengecualian yang sama. Jadi untuk menghindari pengecualian Anda harus menetapkan nol untuk kelas anak dan kemudian membuat induknya. (Contoh Kode)
sumber
Masalah saya terkait dengan
@BeforeEach
JUnit. Dan bahkan jika saya menyimpan entitas terkait (dalam kasus saya@ManyToOne
), saya mendapatkan kesalahan yang sama.Masalahnya entah bagaimana terkait dengan urutan yang saya miliki di orang tua saya. Jika saya menetapkan nilai ke atribut itu, masalahnya terpecahkan.
Ex. Jika saya memiliki Pertanyaan entitas yang dapat memiliki beberapa kategori (satu atau lebih) dan Pertanyaan entitas memiliki urutan:
Saya harus menetapkan nilainya
question.setId(1L);
sumber
Buat Constructor pemetaan Anda di kelas dasar Anda. Seperti jika Anda ingin hubungan One-To-One di Entity A, Entity B. jika Anda mengambil A sebagai kelas dasar, maka A harus memiliki Konstruktor memiliki B sebagai argumen.
sumber