Czy w kontekście braku jest ten błąd? czy jest ze zmienną przejściową czy bez?
vijay
Odpowiedzi:
801
Powinieneś dołączyć cascade="all"(jeśli używasz xml) lub cascade=CascadeType.ALL(jeśli używasz adnotacji) do swojego mapowania kolekcji.
Dzieje się tak, ponieważ masz kolekcję w swojej encji, a ta kolekcja zawiera jeden lub więcej elementów, które nie są obecne w bazie danych. Określając powyższe opcje, każesz hibernacji zapisać je w bazie danych podczas zapisywania ich elementu nadrzędnego.
Czy to nie jest dorozumiane? Czy nie zawsze chciałbyś, aby Hibernacja je uratowała?
Marcus Leon
29
@Marcus - nie, nie jest. Możesz chcieć obsługiwać je ręcznie.
Bozho
5
Bozho ma rację. Napotkałem okoliczności, w których miałem kolekcje, którymi chciałem zarządzać ręcznie ze względu na ich rozmiar lub z powodu reguł biznesowych, które nie zezwalają na jednoczesne zapisywanie wszystkich obiektów w kolekcji.
Alex Marshall,
26
Nie dzieje się tak tylko w przypadku kolekcji, ale także prostych mapowań jeden na jeden
Sebastien Lorber
12
Czy nie lepiej byłoby zacząć od CascadeType.PERSIST i użyć opcji keep, aby zapisać?
Sergii Shevchyk
248
Wierzę, że to może być tylko powtórzenie odpowiedzi, ale dla wyjaśnienia, mam to na @OneToOnemapie, a także @OneToMany. W obu przypadkach był to fakt, że Childobiekt, który dodawałem, Parentnie był jeszcze zapisany w bazie danych. Więc kiedy dodałem Childdo Parent, a następnie zapisałem Parent, Hibernacja podrzuciłaby "object references an unsaved transient instance - save the transient instance before flushing"wiadomość podczas zapisywania Rodzica.
Dodanie w cascade = {CascadeType.ALL}sprawie Parent'sodniesienia do Childrozwiązania problemu w obu przypadkach. To uratowało Childi Parent.
Przepraszamy za powtarzające się odpowiedzi, chciałem tylko wyjaśnić ludziom.
Co jeśli nie chcę kaskadowo zapisywać w relacji @OneToOne? Jak mogę utworzyć oba obiekty po raz pierwszy w bazie danych bez wyzwalania wyjątku?
xtian
4
Co jeśli chcę uratować dziecko w niektórych przypadkach, a nie w innych?
Omaruchan
@xtian: Więc musisz zadbać o właściwą kolejność zapisywania w bazie danych, utrwalając obiekty za pomocą EntityManager. W podstawowym po prostu mówisz em.persist (object1); em.persist (object2); itp.
kaba713,
Ten problem wystąpił konkretnie, gdy użyłem @Inheritance, w tym przypadku TABLE_PER_CLASS odwoływałem się do podklasy. CascadeType.ALL naprawił to.
Jim ReesPotter
Lub utworzyłeś obiekt encji za pomocą new MyEntity(bez synchronizacji z bazą danych - opróżnianie), zamiast pobierania jego zsynchronizowanej instancji z bazy danych. Wykonywanie zapytań Hibernacja przy użyciu tego wystąpienia informuje, że to, czego oczekujesz w bazie danych, różni się od tego, co masz w pamięci aplikacji. W takim przypadku - po prostu zsynchronizuj / pobierz instancję z DB i użyj jej. Wówczas CascadeType.ALL nie jest potrzebny.
Strefa
66
Dzieje się tak podczas zapisywania obiektu, gdy Hibernacja uważa, że musi on zapisać obiekt skojarzony z tym, który zapisujesz.
Miałem ten problem i nie chciałem zapisywać zmian w przywoływanym obiekcie, więc chciałem, aby typ kaskady był BRAK.
Sztuczka polega na upewnieniu się, że identyfikator i WERSJA w przywoływanym obiekcie są ustawione, aby Hibernacja nie uważała, że przywoływany obiekt jest nowym obiektem, który wymaga zapisania. To zadziałało dla mnie.
Przejrzyj wszystkie relacje w zapisywanej klasie, aby opracować powiązane obiekty (i powiązane obiekty powiązanych obiektów) i upewnij się, że ID i WERSJA są ustawione we wszystkich obiektach drzewa obiektów.
Ten komentarz postawił mnie na właściwej drodze. Przypisywałem nową instancję rodzica do właściwości jego dziecka. NH pomyślał, że to różne przypadki.
elvin
2
Tak. Dzieje się tak, jeśli na przykład identyfikator powiązanego obiektu nie jest uwzględniony (np. Został zignorowany przez @JsonIgnore). Hibernacja nie ma możliwości zidentyfikowania powiązanej jednostki, więc chce ją zapisać.
Rori Stumpf
36
Wprowadzenie
Jak wyjaśniłem w tym artykule podczas korzystania z JPA i Hibernacji, jednostka może znajdować się w jednym z następujących 4 stanów:
Nowość - Nowo utworzony obiekt, który nigdy nie był skojarzony z sesją hibernacji (inaczej Kontekst Persistence) i nie jest odwzorowany na żaden wiersz tabeli bazy danych, jest uważany za będący w stanie Nowy lub Przejściowy.
Aby się utrwalić, musimy albo jawnie wywołać tę persistmetodę, albo skorzystać z mechanizmu trwałości przechodniego.
Trwały - trwały byt został powiązany z wierszem tabeli bazy danych i jest zarządzany przez aktualnie działający kontekst trwałości.
Wszelkie zmiany dokonane w takiej jednostce zostaną wykryte i propagowane do bazy danych (podczas czasu opróżniania sesji).
Odłączony - Po zamknięciu aktualnie działającego kontekstu trwałości odłączane są wszystkie wcześniej zarządzane jednostki. Kolejne zmiany nie będą już śledzone i nie nastąpi automatyczna synchronizacja bazy danych.
Usunięte - chociaż JPA wymaga, aby usuwane były tylko zarządzane jednostki, Hibernacja może również usuwać odłączone jednostki (ale tylko poprzez removewywołanie metody).
Przejścia stanu encji
Aby przenieść jednostkę z jednego stanu do drugiego, można użyć persist, removeani mergemetod.
Naprawianie problemu
Problem, który opisujesz w swoim pytaniu:
object references an unsaved transient instance - save the transient instance before flushing
jest spowodowany przez powiązanie encji w stanie Nowy z encją w stanie Zarządzanym .
Może się to zdarzyć, gdy kojarzy się jednostkę podrzędną z kolekcją jeden do wielu w jednostce nadrzędnej, a kolekcja nie cascade stanu encji.
Tak więc, jak wyjaśniłem w tym artykule , możesz to naprawić, dodając kaskadę do powiązania encji, która spowodowała ten błąd, w następujący sposób:
W @ManyToManyzwiązku nie można używać CascadeType.ALLluborphanRemoval ponieważ spowoduje to propagację przejścia stanu usuwania encji z jednego rodzica na inny podmiot nadrzędny.
Dlatego w przypadku @ManyToManyskojarzeń zwykle kaskadowo wykonuje się operacje CascadeType.PERSISTlub CascadeType.MERGE. Alternatywnie możesz rozwinąć to do DETACHlub REFRESH.
Aby uzyskać więcej informacji na temat najlepszego sposobu mapowania @ManyToManypowiązania, sprawdź również ten artykuł .
To powinna być zaakceptowana odpowiedź. CascadeType.ALL jest zbyt szeroki
lilalinux
5
Począwszy od wersji Hibernacji 5.2.8 wydaje się, że nie można osiągnąć tego samego efektu za pomocą adnotacji JPA. Na przykład @ManyToMany(cascade={PERSIST, MERGE, REFRESH, DETACH})(wszystkie oprócz USUŃ) nie kaskadują aktualizacji, jak Hibernacja CascadeType.SAVE_UPDATE.
jcsahnwaldt mówi GoFundMonica
25
W moim przypadku było to spowodowane nie mając CascadeTypena @ManyToOnestronie relacji dwukierunkowej. Mówiąc ściślej, miałem CascadeType.ALLpo @OneToManystronie i nie miałem go na sobie @ManyToOne. Dodawanie w CascadeType.ALLcelu @ManyToOnerozwiązania problemu.
Strona jeden do wielu :
Jeśli zrobię to w ten sposób i zapiszę jednostkę nadrzędną, dzieje się tak, że w mojej tabeli nadrzędnej są dwie wstawki, czyli dwa wiersze. Myślę, że to dlatego, że mamy kaskadę na jednostkach nadrzędnych i podrzędnych?
theprogrammer
18
Stało się to dla mnie, gdy trwałem bytu, w którym istniejący rekord w bazie danych miał wartość NULL dla pola z adnotacją @Version (dla optymistycznego blokowania). Poprawiono wartość NULL do 0 w bazie danych.
To powinno być nowe pytanie i powinno zostać dodane jako błąd, przynajmniej wprowadzający w błąd wyjątek. To okazało się przyczyną mojego problemu.
BML
To rozwiązuje mój problem
Jad Chahine
11
To nie jedyny powód błędu. Spotkałem go właśnie teraz z powodu błędu literowego w moim kodzie, który, jak sądzę, ustawił wartość bytu, który został już zapisany.
X x2 =new X();
x.setXid(memberid);// Error happened here - x was a previous global entity I created earlier
Y.setX(x2);
Zauważyłem błąd, znajdując dokładnie, która zmienna spowodowała błąd (w tym przypadku String xid). Użyłem catchcałego bloku kodu, który uratował byt i wydrukował ślady.
{
code block that performed the operation
}catch(Exception e){
e.printStackTrace();// put a break-point here and inspect the 'e'return ERROR;}
Podobny problem do mojego. W końcu, kiedy ponownie załadowałem jednostkę lokalnie, ustawiłem właściwość, a następnie zapisałem, działała dobrze.
CsBalazsHungary
8
Nie używaj, Cascade.Alldopóki naprawdę nie musisz. Rolei Permissionmają manyToManyrelacje dwukierunkowe . Następnie następujący kod będzie działał poprawnie
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);
podczas gdy jeśli obiekt jest po prostu „nowy”, wygenerowałby ten sam błąd.
jest w 100% poprawny, Cascade. Wszystko jest leniwym rozwiązaniem i powinno być stosowane tylko w razie potrzeby. po pierwsze, jeśli jednostka już istnieje, sprawdź, czy jest załadowana do bieżącego menedżera encji, jeśli nie, załaduj ją.
Renato Mendes,
7
Jeśli twoja kolekcja ma wartość zerową, po prostu spróbuj: object.SetYouColection(null);
To był całkowicie mój problem. Nigdy bym nie przypuszczał, że musiałem ręcznie ustawić na zero.
Deadron,
To był również mój problem. Nie używałem kolekcji, więc nie próbowałem tego na początku, ale ustawiłem mój obiekt na zero, a teraz działa.
Fodder
5
Aby dodać moje 2 centy, dostałem ten sam problem, gdy przypadkowo wysyłam nulljako identyfikator. Poniższy kod przedstawia mój scenariusz (a OP nie wspomniał o żadnym konkretnym scenariuszu) .
Employee emp =newEmployee();
emp.setDept(newDept(deptId));// --> when deptId PKID is null, same error will be thrown// calls to other setters...
em.persist(emp);
Tutaj ustawiam istniejący identyfikator działu na nową instancję pracownika, nie pobierając najpierw jednostki działu, ponieważ nie chcę uruchamiać innego wybranego zapytania.
W niektórych scenariuszach deptIdPKID pochodzi nullod metody wywołania i otrzymuję ten sam błąd.
Mam podobny problem. Otrzymuję wyjątek, gdy mój deptID wynosi 0. Każda inna wartość większa niż 0 działa. Zabawne, że mam dept o id = 0.
Gustavo
5
Ten problem przydarzył mi się, gdy utworzyłem nowy obiekt i powiązany obiekt w metodzie oznaczonej jako @Transactional, a następnie wykonałem zapytanie przed zapisaniem. Dawny
@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);}
Aby to naprawić, wykonałem zapytanie przed utworzeniem nowego obiektu.
oprócz wszystkich innych dobrych odpowiedzi, może się tak zdarzyć, jeśli użyjesz mergedo utrwalenia obiektu i przypadkowo zapomnisz użyć scalonego odwołania do obiektu w klasie nadrzędnej. rozważ następujący przykład
merge(A);
B.setA(A);
persist(B);
W takim przypadku scalasz, Aale zapominasz użyć scalonego obiektu A. aby rozwiązać problem, musisz przepisać kod w ten sposób.
A=merge(A);//difference is here
B.setA(A);
persist(B);
Też spotkałem się z tą samą sytuacją. Ustawienie poniższej adnotacji nad właściwością sprawiło, że rozwiązano zgłoszony wyjątek.
Wyjątek, z którym się spotkałem.
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
Ten wyjątek jest zgłaszany do konsoli, ponieważ obiekt podrzędny, który dołączam do obiektu nadrzędnego, nie jest w tym momencie obecny w bazie danych.
Podając @OneToMany(cascade = {CascadeType.ALL}), informuje Hibernację, aby zapisał je w bazie danych podczas zapisywania obiektu nadrzędnego.
Metoda setNewPassword () tworzy rekord PasswordHistory i dodaje go do kolekcji historii w User. Ponieważ instrukcja create () nie została jeszcze wykonana dla elementu nadrzędnego, próbowała zapisać w kolekcji encji, która nie została jeszcze utworzona. Wszystko, co musiałem zrobić, aby to naprawić, to przenieść wywołanie setNewPassword () po wywołaniu create ().
Istnieje inna możliwość, która może spowodować ten błąd w trybie hibernacji. Możesz ustawić niezapisane odniesienie swojego obiektu Ado dołączonej encji Bi chcesz utrwalić obiekt C. Nawet w tym przypadku otrzymasz wyżej wymieniony błąd.
Myślę, że dzieje się tak, ponieważ próbujesz utrwalić obiekt, który ma odwołanie do innego obiektu, który nie jest jeszcze trwały, i dlatego po stronie DB próbuje umieścić odniesienie do wiersza, który nie istnieje
Prostym sposobem rozwiązania tego problemu jest uratowanie obu podmiotów. najpierw zapisz element potomny, a następnie zapisz element macierzysty. Ponieważ jednostka nadrzędna jest zależna od jednostki podrzędnej dla wartości klucza obcego.
Poniżej prosty egzamin relacji jeden do jednego
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);
Przeciwnie - jednostka potomna posiada wartość FK i zależy od rodzica, więc najpierw musisz zapisać rodzica! W bloku kodu masz rację.
Sõber
0
Jedną z możliwych przyczyn błędu jest nieistnienie ustawienia wartości jednostki dominującej; na przykład dla relacji dział-pracownik musisz to napisać, aby naprawić błąd:
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);
Jest tak wiele możliwości tego błędu, że inne możliwości znajdują się również na stronie dodawania lub edycji strony. W moim przypadku próbowałem zapisać obiekt AdvanceSalary. Problem polega na tym, że w edycji AdvanceSalary pracownik.employee_id ma wartość NULL, ponieważ podczas edycji nie ustawiłem pracownika.employee_id. Zrobiłem ukryte pole i ustawiłem je. mój kod działa absolutnie dobrze.
Spotykałem się z tym wyjątkiem, gdy nie utrwalałem obiektu nadrzędnego, ale zapisywałem dziecko. Aby rozwiązać problem, w tej samej sesji utrwaliłem zarówno obiekty podrzędne, jak i nadrzędne i użyłem CascadeType.ALL na rodzicu.
Przypadek 1: Otrzymałem ten wyjątek, gdy próbowałem utworzyć element nadrzędny i zapisać to odwołanie elementu nadrzędnego do jego elementu podrzędnego, a następnie inne zapytanie DELETE / UPDATE (JPQL). Więc po prostu opróżniam () nowo utworzony byt po utworzeniu elementu nadrzędnego i po utworzeniu elementu podrzędnego przy użyciu tego samego odwołania nadrzędnego. To zadziałało dla mnie.
W powyższym przypadku, gdy rodzic (Reference) i child (ReferenceAdditionalDetails) mają relację OneToOne, a gdy spróbujesz utworzyć obiekt Reference, a następnie jego obiekt potomny (ReferenceAdditionalDetails), otrzymasz ten sam wyjątek. Aby uniknąć wyjątku, musisz ustawić wartość null dla klasy potomnej, a następnie utworzyć element nadrzędny. (Przykładowy kod)
Po prostu uczyń Konstruktorem swojego mapowania w swojej klasie podstawowej. Na przykład, jeśli chcesz relacji jeden-do-jednego w Podmiocie A, Podmiotu B., jeśli bierzesz A jako klasę podstawową, to A musi mieć Konstruktor jako argument B.
Odpowiedzi:
Powinieneś dołączyć
cascade="all"
(jeśli używasz xml) lubcascade=CascadeType.ALL
(jeśli używasz adnotacji) do swojego mapowania kolekcji.Dzieje się tak, ponieważ masz kolekcję w swojej encji, a ta kolekcja zawiera jeden lub więcej elementów, które nie są obecne w bazie danych. Określając powyższe opcje, każesz hibernacji zapisać je w bazie danych podczas zapisywania ich elementu nadrzędnego.
źródło
Wierzę, że to może być tylko powtórzenie odpowiedzi, ale dla wyjaśnienia, mam to na
@OneToOne
mapie, a także@OneToMany
. W obu przypadkach był to fakt, żeChild
obiekt, który dodawałem,Parent
nie był jeszcze zapisany w bazie danych. Więc kiedy dodałemChild
doParent
, a następnie zapisałemParent
, Hibernacja podrzuciłaby"object references an unsaved transient instance - save the transient instance before flushing"
wiadomość podczas zapisywania Rodzica.Dodanie w
cascade = {CascadeType.ALL}
sprawieParent's
odniesienia doChild
rozwiązania problemu w obu przypadkach. To uratowałoChild
iParent
.Przepraszamy za powtarzające się odpowiedzi, chciałem tylko wyjaśnić ludziom.
źródło
new MyEntity
(bez synchronizacji z bazą danych - opróżnianie), zamiast pobierania jego zsynchronizowanej instancji z bazy danych. Wykonywanie zapytań Hibernacja przy użyciu tego wystąpienia informuje, że to, czego oczekujesz w bazie danych, różni się od tego, co masz w pamięci aplikacji. W takim przypadku - po prostu zsynchronizuj / pobierz instancję z DB i użyj jej. Wówczas CascadeType.ALL nie jest potrzebny.Dzieje się tak podczas zapisywania obiektu, gdy Hibernacja uważa, że musi on zapisać obiekt skojarzony z tym, który zapisujesz.
Miałem ten problem i nie chciałem zapisywać zmian w przywoływanym obiekcie, więc chciałem, aby typ kaskady był BRAK.
Sztuczka polega na upewnieniu się, że identyfikator i WERSJA w przywoływanym obiekcie są ustawione, aby Hibernacja nie uważała, że przywoływany obiekt jest nowym obiektem, który wymaga zapisania. To zadziałało dla mnie.
Przejrzyj wszystkie relacje w zapisywanej klasie, aby opracować powiązane obiekty (i powiązane obiekty powiązanych obiektów) i upewnij się, że ID i WERSJA są ustawione we wszystkich obiektach drzewa obiektów.
źródło
Wprowadzenie
Jak wyjaśniłem w tym artykule podczas korzystania z JPA i Hibernacji, jednostka może znajdować się w jednym z następujących 4 stanów:
Nowość - Nowo utworzony obiekt, który nigdy nie był skojarzony z sesją hibernacji (inaczej Kontekst Persistence) i nie jest odwzorowany na żaden wiersz tabeli bazy danych, jest uważany za będący w stanie Nowy lub Przejściowy.
Aby się utrwalić, musimy albo jawnie wywołać tę
persist
metodę, albo skorzystać z mechanizmu trwałości przechodniego.Trwały - trwały byt został powiązany z wierszem tabeli bazy danych i jest zarządzany przez aktualnie działający kontekst trwałości.
Wszelkie zmiany dokonane w takiej jednostce zostaną wykryte i propagowane do bazy danych (podczas czasu opróżniania sesji).
Odłączony - Po zamknięciu aktualnie działającego kontekstu trwałości odłączane są wszystkie wcześniej zarządzane jednostki. Kolejne zmiany nie będą już śledzone i nie nastąpi automatyczna synchronizacja bazy danych.
Usunięte - chociaż JPA wymaga, aby usuwane były tylko zarządzane jednostki, Hibernacja może również usuwać odłączone jednostki (ale tylko poprzez
remove
wywołanie metody).Przejścia stanu encji
Aby przenieść jednostkę z jednego stanu do drugiego, można użyć
persist
,remove
animerge
metod.Naprawianie problemu
Problem, który opisujesz w swoim pytaniu:
jest spowodowany przez powiązanie encji w stanie Nowy z encją w stanie Zarządzanym .
Może się to zdarzyć, gdy kojarzy się jednostkę podrzędną z kolekcją jeden do wielu w jednostce nadrzędnej, a kolekcja nie
cascade
stanu encji.Tak więc, jak wyjaśniłem w tym artykule , możesz to naprawić, dodając kaskadę do powiązania encji, która spowodowała ten błąd, w następujący sposób:
@OneToOne
stowarzyszenie@OneToMany
stowarzyszeniePonownie
CascadeType.ALL
nadaje się do skojarzeń dwukierunkowych@OneToMany
.Teraz, aby kaskada działała poprawnie w trybie dwukierunkowym, musisz także upewnić się, że skojarzenia nadrzędne i podrzędne są zsynchronizowane.
@ManyToMany
stowarzyszenieW
@ManyToMany
związku nie można używaćCascadeType.ALL
luborphanRemoval
ponieważ spowoduje to propagację przejścia stanu usuwania encji z jednego rodzica na inny podmiot nadrzędny.Dlatego w przypadku
@ManyToMany
skojarzeń zwykle kaskadowo wykonuje się operacjeCascadeType.PERSIST
lubCascadeType.MERGE
. Alternatywnie możesz rozwinąć to doDETACH
lubREFRESH
.źródło
Lub, jeśli chcesz użyć minimalnych „mocy” (np. Jeśli nie chcesz kasować kasowania), aby osiągnąć to, czego chcesz, użyj
źródło
@ManyToMany(cascade={PERSIST, MERGE, REFRESH, DETACH})
(wszystkie oprócz USUŃ) nie kaskadują aktualizacji, jak HibernacjaCascadeType.SAVE_UPDATE
.W moim przypadku było to spowodowane nie mając
CascadeType
na@ManyToOne
stronie relacji dwukierunkowej. Mówiąc ściślej, miałemCascadeType.ALL
po@OneToMany
stronie i nie miałem go na sobie@ManyToOne
. Dodawanie wCascadeType.ALL
celu@ManyToOne
rozwiązania problemu. Strona jeden do wielu :Strona wiele do jednego (spowodowała problem)
Wiele do jednego (naprawione przez dodanie
CascadeType.PERSIST
)źródło
Stało się to dla mnie, gdy trwałem bytu, w którym istniejący rekord w bazie danych miał wartość NULL dla pola z adnotacją @Version (dla optymistycznego blokowania). Poprawiono wartość NULL do 0 w bazie danych.
źródło
To nie jedyny powód błędu. Spotkałem go właśnie teraz z powodu błędu literowego w moim kodzie, który, jak sądzę, ustawił wartość bytu, który został już zapisany.
Zauważyłem błąd, znajdując dokładnie, która zmienna spowodowała błąd (w tym przypadku
String xid
). Użyłemcatch
całego bloku kodu, który uratował byt i wydrukował ślady.źródło
Nie używaj,
Cascade.All
dopóki naprawdę nie musisz.Role
iPermission
mająmanyToMany
relacje dwukierunkowe . Następnie następujący kod będzie działał poprawniepodczas gdy jeśli obiekt jest po prostu „nowy”, wygenerowałby ten sam błąd.
źródło
Jeśli twoja kolekcja ma wartość zerową, po prostu spróbuj:
object.SetYouColection(null);
źródło
Aby dodać moje 2 centy, dostałem ten sam problem, gdy przypadkowo wysyłam
null
jako identyfikator. Poniższy kod przedstawia mój scenariusz (a OP nie wspomniał o żadnym konkretnym scenariuszu) .Tutaj ustawiam istniejący identyfikator działu na nową instancję pracownika, nie pobierając najpierw jednostki działu, ponieważ nie chcę uruchamiać innego wybranego zapytania.
W niektórych scenariuszach
deptId
PKID pochodzinull
od metody wywołania i otrzymuję ten sam błąd.Uważaj więc na
null
wartości dla PK IDźródło
Ten problem przydarzył mi się, gdy utworzyłem nowy obiekt i powiązany obiekt w metodzie oznaczonej jako
@Transactional
, a następnie wykonałem zapytanie przed zapisaniem. DawnyAby to naprawić, wykonałem zapytanie przed utworzeniem nowego obiektu.
źródło
oprócz wszystkich innych dobrych odpowiedzi, może się tak zdarzyć, jeśli użyjesz
merge
do utrwalenia obiektu i przypadkowo zapomnisz użyć scalonego odwołania do obiektu w klasie nadrzędnej. rozważ następujący przykładW takim przypadku scalasz,
A
ale zapominasz użyć scalonego obiektuA
. aby rozwiązać problem, musisz przepisać kod w ten sposób.źródło
pojawia się ten błąd, gdy korzystam
ale działa bez problemu, gdy używam
źródło
Też spotkałem się z tą samą sytuacją. Ustawienie poniższej adnotacji nad właściwością sprawiło, że rozwiązano zgłoszony wyjątek.
Wyjątek, z którym się spotkałem.
Aby przezwyciężyć, użyłem adnotacji.
Co sprawiło, że Hibernacja rzuciła wyjątek:
Ten wyjątek jest zgłaszany do konsoli, ponieważ obiekt podrzędny, który dołączam do obiektu nadrzędnego, nie jest w tym momencie obecny w bazie danych.
Podając
@OneToMany(cascade = {CascadeType.ALL})
, informuje Hibernację, aby zapisał je w bazie danych podczas zapisywania obiektu nadrzędnego.źródło
Dla kompletności: A
z wiadomością
pojawi się również, gdy spróbujesz utrwalić / scalić byt z odniesieniem do innego bytu, który przypadkowo zostanie odłączony .
źródło
Jeszcze jeden możliwy powód: w moim przypadku próbowałem uratować dziecko przed uratowaniem rodzica, na zupełnie nowej jednostce.
Kod wyglądał mniej więcej tak w modelu User.java:
Metoda setNewPassword () tworzy rekord PasswordHistory i dodaje go do kolekcji historii w User. Ponieważ instrukcja create () nie została jeszcze wykonana dla elementu nadrzędnego, próbowała zapisać w kolekcji encji, która nie została jeszcze utworzona. Wszystko, co musiałem zrobić, aby to naprawić, to przenieść wywołanie setNewPassword () po wywołaniu create ().
źródło
Istnieje inna możliwość, która może spowodować ten błąd w trybie hibernacji. Możesz ustawić niezapisane odniesienie swojego obiektu
A
do dołączonej encjiB
i chcesz utrwalić obiektC
. Nawet w tym przypadku otrzymasz wyżej wymieniony błąd.źródło
Jeśli używasz JPA Spring Data, dodanie
@Transactional
adnotacji do implementacji usługi rozwiązałoby problem.źródło
Myślę, że dzieje się tak, ponieważ próbujesz utrwalić obiekt, który ma odwołanie do innego obiektu, który nie jest jeszcze trwały, i dlatego po stronie DB próbuje umieścić odniesienie do wiersza, który nie istnieje
źródło
Prostym sposobem rozwiązania tego problemu jest uratowanie obu podmiotów. najpierw zapisz element potomny, a następnie zapisz element macierzysty. Ponieważ jednostka nadrzędna jest zależna od jednostki podrzędnej dla wartości klucza obcego.
Poniżej prosty egzamin relacji jeden do jednego
źródło
Jedną z możliwych przyczyn błędu jest nieistnienie ustawienia wartości jednostki dominującej; na przykład dla relacji dział-pracownik musisz to napisać, aby naprawić błąd:
źródło
Jest tak wiele możliwości tego błędu, że inne możliwości znajdują się również na stronie dodawania lub edycji strony. W moim przypadku próbowałem zapisać obiekt AdvanceSalary. Problem polega na tym, że w edycji AdvanceSalary pracownik.employee_id ma wartość NULL, ponieważ podczas edycji nie ustawiłem pracownika.employee_id. Zrobiłem ukryte pole i ustawiłem je. mój kod działa absolutnie dobrze.
źródło
Spotykałem się z tym wyjątkiem, gdy nie utrwalałem obiektu nadrzędnego, ale zapisywałem dziecko. Aby rozwiązać problem, w tej samej sesji utrwaliłem zarówno obiekty podrzędne, jak i nadrzędne i użyłem CascadeType.ALL na rodzicu.
źródło
Przypadek 1: Otrzymałem ten wyjątek, gdy próbowałem utworzyć element nadrzędny i zapisać to odwołanie elementu nadrzędnego do jego elementu podrzędnego, a następnie inne zapytanie DELETE / UPDATE (JPQL). Więc po prostu opróżniam () nowo utworzony byt po utworzeniu elementu nadrzędnego i po utworzeniu elementu podrzędnego przy użyciu tego samego odwołania nadrzędnego. To zadziałało dla mnie.
Przypadek 2:
Klasa rodzicielska
Klasa dla dzieci:
W powyższym przypadku, gdy rodzic (Reference) i child (ReferenceAdditionalDetails) mają relację OneToOne, a gdy spróbujesz utworzyć obiekt Reference, a następnie jego obiekt potomny (ReferenceAdditionalDetails), otrzymasz ten sam wyjątek. Aby uniknąć wyjątku, musisz ustawić wartość null dla klasy potomnej, a następnie utworzyć element nadrzędny. (Przykładowy kod)
źródło
Mój problem dotyczył
@BeforeEach
JUnit. I nawet jeśli zapisałem powiązane podmioty (w moim przypadku@ManyToOne
), dostałem ten sam błąd.Problem jest w jakiś sposób związany z sekwencją, którą mam u rodzica. Jeśli przypiszę wartość do tego atrybutu, problem zostanie rozwiązany.
Dawny. Jeśli mam pytanie encji, które może mieć pewne kategorie (jedną lub więcej), a pytanie encji ma sekwencję:
Muszę przypisać wartość
question.setId(1L);
źródło
Po prostu uczyń Konstruktorem swojego mapowania w swojej klasie podstawowej. Na przykład, jeśli chcesz relacji jeden-do-jednego w Podmiocie A, Podmiotu B., jeśli bierzesz A jako klasę podstawową, to A musi mieć Konstruktor jako argument B.
źródło