Comment réparer la mise en veille prolongée de l'objet «fait référence à une instance transitoire non enregistrée - enregistrez l'instance transitoire avant de vider»
610
Je reçois l'erreur suivante lorsque j'enregistre l'objet à l'aide d'Hibernate
object references an unsaved transient instance - save the transient instance before flushing
Dans le contexte voulu, cette erreur? est-ce avec ou sans variable transitoire?
vijay
Réponses:
803
Vous devez inclure cascade="all"(si vous utilisez xml) ou cascade=CascadeType.ALL(si vous utilisez des annotations) sur le mappage de votre collection.
Cela se produit car vous avez une collection dans votre entité et cette collection a un ou plusieurs éléments qui ne sont pas présents dans la base de données. En spécifiant les options ci-dessus, vous dites à hibernate de les enregistrer dans la base de données lors de l'enregistrement de leur parent.
N'est-ce pas implicite? Ne voudriez-vous pas toujours qu'Hibernate les enregistre?
Marcus Leon
29
@Marcus - non, ce n'est pas le cas. Vous voudrez peut-être les gérer manuellement.
Bozho
5
Bozho a raison. J'ai rencontré des circonstances dans lesquelles j'avais des collections que je voulais gérer manuellement en raison de leur taille ou en raison de règles métier qui ne permettent pas à tous les objets d'une collection d'être enregistrés en même temps.
Alex Marshall
26
Cela ne se produit pas seulement pour les collections, mais aussi pour les mappings simples un à un
Sebastien Lorber
12
Ne serait-il pas préférable de commencer avec CascadeType.PERSIST et d'utiliser persist pour enregistrer?
Sergii Shevchyk
249
Je crois que cela pourrait être juste une réponse répétée, mais juste pour clarifier, j'ai obtenu ceci sur une @OneToOnecartographie ainsi que sur un @OneToMany. Dans les deux cas, c'était le fait que l' Childobjet que j'ajoutais Parentn'était pas encore enregistré dans la base de données. Ainsi, lorsque j'ajoutais le Childà Parent, puis enregistrais le Parent, Hibernate lancerait le "object references an unsaved transient instance - save the transient instance before flushing"message lors de l'enregistrement du parent.
Ajout dans le cascade = {CascadeType.ALL}sur la Parent'sréférence au Childrésoudre le problème dans les deux cas. Cela a sauvé le Childet le Parent.
Désolé pour toutes les réponses répétées, je voulais juste clarifier davantage pour les gens.
Que se passe-t-il si je ne souhaite pas enregistrer en cascade les économies sur une relation @OneToOne? Lors de la création des deux objets pour la première fois, comment puis-je enregistrer l'un ou l'autre dans la base de données sans déclencher l'exception?
2016
4
Et si je veux sauver l'enfant pour certains cas et pas pour d'autres?
Omaruchan
@xtian: Eh bien, vous devez prendre soin du bon ordre d'enregistrement dans la base de données en conservant les objets avec un EntityManager. En base, vous dites simplement em.persist (object1); em.persist (object2); etc.
kaba713
J'ai rencontré ce problème spécifiquement lorsque j'ai utilisé @Inheritance, dans ce cas TABLE_PER_CLASS, je faisais référence à une sous-classe. CascadeType.ALL l'a corrigé.
Jim ReesPotter
Ou vous avez créé votre objet entité avec new MyEntity(sans le synchroniser avec la base de données - vidage), au lieu d'obtenir son instance synchronisée de la base de données. Faire des requêtes Hibernate en utilisant cette instance vous informe que ce que vous attendez d'être dans la base de données diffère de ce que vous avez dans la mémoire de votre application. Dans ce cas, synchronisez / obtenez simplement votre entité à partir de la base de données et utilisez-la. Aucun CascadeType.ALL n'est alors nécessaire.
Zon
67
Cela se produit lors de l'enregistrement d'un objet lorsque Hibernate pense qu'il doit enregistrer un objet associé à celui que vous enregistrez.
J'ai eu ce problème et je ne voulais pas enregistrer les modifications apportées à l'objet référencé, je voulais donc que le type de cascade soit AUCUN.
L'astuce consiste à s'assurer que l'ID et la VERSION dans l'objet référencé sont définis de sorte que Hibernate ne pense pas que l'objet référencé est un nouvel objet qui doit être enregistré. Cela a fonctionné pour moi.
Parcourez toutes les relations de la classe que vous enregistrez pour déterminer les objets associés (et les objets associés des objets associés) et assurez-vous que l'ID et la VERSION sont définis dans tous les objets de l'arborescence d'objets.
Ce commentaire m'a mis sur la bonne voie. J'assignais une nouvelle instance du parent dans une propriété de son enfant. NH a donc pensé qu'il s'agissait de cas différents.
elvin
2
Oui. Cela se produit si, par exemple, l'id de l'objet associé n'est pas inclus (par exemple, il a été ignoré par @JsonIgnore). Hibernate n'a aucun moyen d'identifier l'entité associée, il souhaite donc la sauvegarder.
Rori Stumpf
36
introduction
Comme je l'ai expliqué dans cet article lors de l'utilisation de JPA et Hibernate, une entité peut se trouver dans l'un des 4 états suivants:
Nouveau - Un objet nouvellement créé qui n'a jamais été associé à une session de mise en veille prolongée (aka Contexte de persistance) et qui n'est mappé à aucune ligne de table de base de données est considéré comme étant à l'état Nouveau ou Transitoire.
Pour devenir persistant, nous devons soit appeler explicitement la persistméthode, soit utiliser le mécanisme de persistance transitive.
Persistant - Une entité persistante a été associée à une ligne de table de base de données et elle est gérée par le contexte de persistance en cours d'exécution.
Toute modification apportée à une telle entité va être détectée et propagée à la base de données (pendant le vidage de session).
Détaché - Une fois que le contexte de persistance en cours d'exécution est fermé, toutes les entités précédemment gérées se détachent. Les modifications successives ne seront plus suivies et aucune synchronisation automatique de la base de données ne se produira.
Supprimé - Bien que JPA exige que seules les entités gérées soient supprimées, Hibernate peut également supprimer les entités détachées (mais uniquement via un removeappel de méthode).
Transitions d'état d'entité
Pour déplacer une entité d'un état à l'autre, vous pouvez utiliser les méthodes persist, removeou merge.
Résoudre le problème
Le problème que vous décrivez dans votre question:
object references an unsaved transient instance - save the transient instance before flushing
est causée par l'association d'une entité à l'état Nouveau à une entité à l'état Géré .
Cela peut se produire lorsque vous associez une entité enfant à une collection un à plusieurs dans l'entité parent et que la collection ne cascade les transitions d'état d'entité.
Ainsi, comme je l'ai expliqué dans cet article , vous pouvez résoudre ce problème en ajoutant une cascade à l'association d'entité qui a déclenché cet échec, comme suit:
Maintenant, pour que la cascade fonctionne correctement dans un sens bidirectionnel, vous devez également vous assurer que les associations parent et enfant sont synchronisées.
Consultez cet article pour plus de détails sur la meilleure façon d'atteindre cet objectif.
Dans une @ManyToManyassociation, vous ne pouvez pas utiliser CascadeType.ALLouorphanRemoval car cela propagera la transition d'état de suppression de l'entité d'un parent à une autre entité parent.
Par conséquent, pour les @ManyToManyassociations, vous mettez généralement en cascade les opérations CascadeType.PERSISTor CascadeType.MERGE. Vous pouvez également l'étendre à DETACHou REFRESH.
Pour plus de détails sur la meilleure façon de mapper une @ManyToManyassociation, consultez également cet article .
Vous pouvez trouver des centaines de ces explications détaillées dans mon tutoriel Hibernate .
Vlad Mihalcea
30
Ou, si vous voulez utiliser un minimum de "pouvoirs" (par exemple si vous ne voulez pas une suppression en cascade) pour obtenir ce que vous voulez, utilisez
Ce devrait être la réponse acceptée. CascadeType.ALL est trop large
lilalinux
5
Depuis Hibernate 5.2.8, il semble qu'il n'y ait aucun moyen d'obtenir le même effet avec les annotations JPA. Par exemple, @ManyToMany(cascade={PERSIST, MERGE, REFRESH, DETACH})(tout sauf REMOVE) ne met pas en cascade les mises à jour comme le fait Hibernate CascadeType.SAVE_UPDATE.
jcsahnwaldt dit GoFundMonica
25
Dans mon cas, cela a été causé par le fait de ne pas être CascadeTypedu @ManyToOnecôté de la relation bidirectionnelle. Pour être plus précis, je l'avais CascadeType.ALLsur le @OneToManycôté et je ne l'avais pas @ManyToOne. Ajout CascadeType.ALLpour @ManyToOnerésoudre le problème.
Côté un à plusieurs :
Si je le fais de cette façon et que j'enregistre l'entité parent, ce qui se passe, c'est qu'il y a deux insertions dans ma table parent qui sont deux lignes. Je pense que c'est parce que nous avons une cascade sur les entités parent et enfant?
theprogrammer
18
Cela s'est produit pour moi lors de la persistance d'une entité dans laquelle l'enregistrement existant dans la base de données avait une valeur NULL pour le champ annoté avec @Version (pour un verrouillage optimiste). La mise à jour de la valeur NULL à 0 dans la base de données a corrigé cela.
Cela devrait être une nouvelle question et elle devrait être ajoutée en tant que bogue, au moins l'exception trompeuse. Cela s'est avéré être la cause de mon problème.
BML
Cela résout mon problème
Jad Chahine
11
Ce n'est pas la seule raison de l'erreur. Je l'ai rencontré tout à l'heure pour une erreur de frappe dans mon codage, qui, je crois, a défini une valeur d'une entité qui était déjà enregistrée.
X x2 =new X();
x.setXid(memberid);// Error happened here - x was a previous global entity I created earlier
Y.setX(x2);
J'ai repéré l'erreur en trouvant exactement quelle variable a causé l'erreur (dans ce cas String xid). J'ai utilisé un catchautour du bloc de code entier qui a sauvé l'entité et imprimé les traces.
{
code block that performed the operation
}catch(Exception e){
e.printStackTrace();// put a break-point here and inspect the 'e'return ERROR;}
Problème similaire au mien. Après tout, lorsque j'ai rechargé l'entité localement, défini la propriété, puis enregistré, cela a bien fonctionné.
CsBalazsHungary
8
N'utilisez pas Cascade.Allavant d'avoir vraiment besoin. Roleet Permissionont une manyToManyrelation bidirectionnelle . Ensuite, le code suivant fonctionnerait bien
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);
tandis que si l'objet est juste un "nouveau", alors il lancerait la même erreur.
est 100% correct, le Cascade.Tout est la solution paresseuse et ne doit être appliqué que lorsque cela est nécessaire. tout d'abord, si l'entité existe déjà, vérifiez si elle est chargée dans le gestionnaire d'entités actuel, sinon chargez-la.
Renato Mendes
7
Si votre collection est nullable, essayez simplement: object.SetYouColection(null);
C'était totalement mon problème. Je n'aurais jamais pensé que je devais le régler manuellement sur null.
Deadron
C'était aussi mon problème. Je n'utilisais pas de collection, donc je n'ai pas essayé au début, mais j'ai défini mon objet sur null et maintenant cela fonctionne.
Fodder
5
Pour ajouter mes 2 cents, j'ai eu ce même problème lorsque j'envoyais accidentellement nullcomme ID. Le code ci-dessous décrit mon scénario (et OP n'a mentionné aucun scénario spécifique) .
Employee emp =newEmployee();
emp.setDept(newDept(deptId));// --> when deptId PKID is null, same error will be thrown// calls to other setters...
em.persist(emp);
Ici, je mets l'ID de service existant sur une nouvelle instance d'employé sans obtenir d'abord l'entité de service, car je ne veux pas qu'une autre requête de sélection se déclenche.
Dans certains scénarios, deptIdPKID arrive commenull de la méthode d'appel et la même erreur.
J'ai un problème similaire. J'obtiens l'exception lorsque mon deptID est 0. Toute autre valeur supérieure à 0 fonctionne. C'est drôle que j'ai un département avec id = 0.
Gustavo
5
Ce problème m'est arrivé lorsque j'ai créé une nouvelle entité et une entité associée dans une méthode marquée comme @Transactional, puis effectué une requête avant d'enregistrer. 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);}
Pour corriger, j'ai effectué la requête avant de créer la nouvelle entité.
à côté de toutes les autres bonnes réponses, cela peut se produire si vous utilisez mergepour conserver un objet et oubliez accidentellement d'utiliser la référence fusionnée de l'objet dans la classe parent. considérons l'exemple suivant
merge(A);
B.setA(A);
persist(B);
Dans ce cas, vous fusionnez Amais oubliez d'utiliser l'objet fusionné de A. pour résoudre le problème, vous devez réécrire le code comme ceci.
A=merge(A);//difference is here
B.setA(A);
persist(B);
J'ai également fait face à la même situation. En définissant l'annotation suivante au-dessus de la propriété, elle résout l'exception demandée.
L'exception que j'ai rencontrée.
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
Cette exception est levée sur votre console car l'objet enfant que j'attache à l'objet parent n'est pas présent dans la base de données à ce moment.
En fournissant @OneToMany(cascade = {CascadeType.ALL}), il indique à Hibernate de les enregistrer dans la base de données tout en enregistrant l'objet parent.
La méthode setNewPassword () crée un enregistrement PasswordHistory et l'ajoute à la collection d'historique dans User. Étant donné que l'instruction create () n'avait pas encore été exécutée pour le parent, elle tentait de l'enregistrer dans une collection d'une entité qui n'avait pas encore été créée. Tout ce que j'avais à faire pour y remédier était de déplacer l'appel setNewPassword () après l'appel à create ().
Il existe une autre possibilité qui peut provoquer cette erreur en veille prolongée. Vous pouvez définir une référence non enregistrée de votre objet Asur une entité attachée Bet vouloir conserver un objet C. Même dans ce cas, vous obtiendrez l'erreur susmentionnée.
Je pense que c'est parce que vous avez essayé de faire persister un objet qui a une référence à un autre objet qui n'est pas encore persistant, et donc il essaie du "côté DB" de mettre une référence à une ligne qui n'existe pas
Un moyen simple de résoudre ce problème consiste à enregistrer les deux entités. enregistrez d'abord l'entité enfant, puis enregistrez l'entité parent. Parce que l'entité parent dépend de l'entité enfant pour la valeur de clé étrangère.
Ci-dessous un simple examen d'une relation un à un
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);
C'est l'opposé - l'entité enfant détient la valeur FK et dépend du parent, vous devez donc d'abord enregistrer le parent! Dans le bloc de code, vous avez raison.
2017
0
Une cause possible de l'erreur est l'inexistence du réglage de la valeur de l'entité parent; Par exemple, pour une relation département-employés, vous devez écrire ceci afin de corriger l'erreur:
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);
Il y a tellement de possibilités de cette erreur, d'autres possibilités sont également sur la page d'ajout ou la page d'édition. Dans mon cas, j'essayais d'enregistrer un objet AdvanceSalary. Le problème est que lors de la modification, AdvanceSalary employee.employee_id est null car lors de la modification, je n'ai pas défini l'employé.employee_id. J'ai créé un champ caché et je l'ai défini. mon code fonctionne très bien.
J'ai fait face à cette exception lorsque je n'ai pas persisté d'objet parent mais que je sauvais l'enfant. Pour résoudre le problème, avec dans la même session, j'ai persisté les objets enfant et parent et utilisé CascadeType.ALL sur le parent.
Cas 1: J'obtenais cette exception lorsque j'essayais de créer un parent et d'enregistrer cette référence parent à son enfant, puis une autre requête DELETE / UPDATE (JPQL). Je viens donc de vider () l'entité nouvellement créée après avoir créé un parent et après avoir créé un enfant en utilisant la même référence parent. Cela a fonctionné pour moi.
Dans le cas ci-dessus, où le parent (Reference) et l'enfant (ReferenceAdditionalDetails) ont une relation OneToOne et lorsque vous essayez de créer une entité Reference, puis son enfant (ReferenceAdditionalDetails), cela vous donnera la même exception. Donc, pour éviter l'exception, vous devez définir null pour la classe enfant, puis créer le parent. (Exemple de code)
Créez simplement Constructeur de votre mapping dans votre classe de base. Comme si vous voulez une relation un à un dans l'entité A, l'entité B. si vous prenez A comme classe de base, alors A doit avoir un constructeur avec B comme argument.
Réponses:
Vous devez inclure
cascade="all"
(si vous utilisez xml) oucascade=CascadeType.ALL
(si vous utilisez des annotations) sur le mappage de votre collection.Cela se produit car vous avez une collection dans votre entité et cette collection a un ou plusieurs éléments qui ne sont pas présents dans la base de données. En spécifiant les options ci-dessus, vous dites à hibernate de les enregistrer dans la base de données lors de l'enregistrement de leur parent.
la source
Je crois que cela pourrait être juste une réponse répétée, mais juste pour clarifier, j'ai obtenu ceci sur une
@OneToOne
cartographie ainsi que sur un@OneToMany
. Dans les deux cas, c'était le fait que l'Child
objet que j'ajoutaisParent
n'était pas encore enregistré dans la base de données. Ainsi, lorsque j'ajoutais leChild
àParent
, puis enregistrais leParent
, Hibernate lancerait le"object references an unsaved transient instance - save the transient instance before flushing"
message lors de l'enregistrement du parent.Ajout dans le
cascade = {CascadeType.ALL}
sur laParent's
référence auChild
résoudre le problème dans les deux cas. Cela a sauvé leChild
et leParent
.Désolé pour toutes les réponses répétées, je voulais juste clarifier davantage pour les gens.
la source
new MyEntity
(sans le synchroniser avec la base de données - vidage), au lieu d'obtenir son instance synchronisée de la base de données. Faire des requêtes Hibernate en utilisant cette instance vous informe que ce que vous attendez d'être dans la base de données diffère de ce que vous avez dans la mémoire de votre application. Dans ce cas, synchronisez / obtenez simplement votre entité à partir de la base de données et utilisez-la. Aucun CascadeType.ALL n'est alors nécessaire.Cela se produit lors de l'enregistrement d'un objet lorsque Hibernate pense qu'il doit enregistrer un objet associé à celui que vous enregistrez.
J'ai eu ce problème et je ne voulais pas enregistrer les modifications apportées à l'objet référencé, je voulais donc que le type de cascade soit AUCUN.
L'astuce consiste à s'assurer que l'ID et la VERSION dans l'objet référencé sont définis de sorte que Hibernate ne pense pas que l'objet référencé est un nouvel objet qui doit être enregistré. Cela a fonctionné pour moi.
Parcourez toutes les relations de la classe que vous enregistrez pour déterminer les objets associés (et les objets associés des objets associés) et assurez-vous que l'ID et la VERSION sont définis dans tous les objets de l'arborescence d'objets.
la source
introduction
Comme je l'ai expliqué dans cet article lors de l'utilisation de JPA et Hibernate, une entité peut se trouver dans l'un des 4 états suivants:
Nouveau - Un objet nouvellement créé qui n'a jamais été associé à une session de mise en veille prolongée (aka Contexte de persistance) et qui n'est mappé à aucune ligne de table de base de données est considéré comme étant à l'état Nouveau ou Transitoire.
Pour devenir persistant, nous devons soit appeler explicitement la
persist
méthode, soit utiliser le mécanisme de persistance transitive.Persistant - Une entité persistante a été associée à une ligne de table de base de données et elle est gérée par le contexte de persistance en cours d'exécution.
Toute modification apportée à une telle entité va être détectée et propagée à la base de données (pendant le vidage de session).
Détaché - Une fois que le contexte de persistance en cours d'exécution est fermé, toutes les entités précédemment gérées se détachent. Les modifications successives ne seront plus suivies et aucune synchronisation automatique de la base de données ne se produira.
Supprimé - Bien que JPA exige que seules les entités gérées soient supprimées, Hibernate peut également supprimer les entités détachées (mais uniquement via un
remove
appel de méthode).Transitions d'état d'entité
Pour déplacer une entité d'un état à l'autre, vous pouvez utiliser les méthodes
persist
,remove
oumerge
.Résoudre le problème
Le problème que vous décrivez dans votre question:
est causée par l'association d'une entité à l'état Nouveau à une entité à l'état Géré .
Cela peut se produire lorsque vous associez une entité enfant à une collection un à plusieurs dans l'entité parent et que la collection ne
cascade
les transitions d'état d'entité.Ainsi, comme je l'ai expliqué dans cet article , vous pouvez résoudre ce problème en ajoutant une cascade à l'association d'entité qui a déclenché cet échec, comme suit:
L'
@OneToOne
associationL'
@OneToMany
associationEncore une fois, le
CascadeType.ALL
convient aux associations bidirectionnelles@OneToMany
.Maintenant, pour que la cascade fonctionne correctement dans un sens bidirectionnel, vous devez également vous assurer que les associations parent et enfant sont synchronisées.
L'
@ManyToMany
associationDans une
@ManyToMany
association, vous ne pouvez pas utiliserCascadeType.ALL
ouorphanRemoval
car cela propagera la transition d'état de suppression de l'entité d'un parent à une autre entité parent.Par conséquent, pour les
@ManyToMany
associations, vous mettez généralement en cascade les opérationsCascadeType.PERSIST
orCascadeType.MERGE
. Vous pouvez également l'étendre àDETACH
ouREFRESH
.la source
Ou, si vous voulez utiliser un minimum de "pouvoirs" (par exemple si vous ne voulez pas une suppression en cascade) pour obtenir ce que vous voulez, utilisez
la source
@ManyToMany(cascade={PERSIST, MERGE, REFRESH, DETACH})
(tout sauf REMOVE) ne met pas en cascade les mises à jour comme le fait HibernateCascadeType.SAVE_UPDATE
.Dans mon cas, cela a été causé par le fait de ne pas être
CascadeType
du@ManyToOne
côté de la relation bidirectionnelle. Pour être plus précis, je l'avaisCascadeType.ALL
sur le@OneToMany
côté et je ne l'avais pas@ManyToOne
. AjoutCascadeType.ALL
pour@ManyToOne
résoudre le problème. Côté un à plusieurs :Côté plusieurs-à-un (a causé le problème)
Plusieurs à un (corrigé en ajoutant
CascadeType.PERSIST
)la source
Cela s'est produit pour moi lors de la persistance d'une entité dans laquelle l'enregistrement existant dans la base de données avait une valeur NULL pour le champ annoté avec @Version (pour un verrouillage optimiste). La mise à jour de la valeur NULL à 0 dans la base de données a corrigé cela.
la source
Ce n'est pas la seule raison de l'erreur. Je l'ai rencontré tout à l'heure pour une erreur de frappe dans mon codage, qui, je crois, a défini une valeur d'une entité qui était déjà enregistrée.
J'ai repéré l'erreur en trouvant exactement quelle variable a causé l'erreur (dans ce cas
String xid
). J'ai utilisé uncatch
autour du bloc de code entier qui a sauvé l'entité et imprimé les traces.la source
N'utilisez pas
Cascade.All
avant d'avoir vraiment besoin.Role
etPermission
ont unemanyToMany
relation bidirectionnelle . Ensuite, le code suivant fonctionnerait bientandis que si l'objet est juste un "nouveau", alors il lancerait la même erreur.
la source
Si votre collection est nullable, essayez simplement:
object.SetYouColection(null);
la source
Pour ajouter mes 2 cents, j'ai eu ce même problème lorsque j'envoyais accidentellement
null
comme ID. Le code ci-dessous décrit mon scénario (et OP n'a mentionné aucun scénario spécifique) .Ici, je mets l'ID de service existant sur une nouvelle instance d'employé sans obtenir d'abord l'entité de service, car je ne veux pas qu'une autre requête de sélection se déclenche.
Dans certains scénarios,
deptId
PKID arrive commenull
de la méthode d'appel et la même erreur.Alors, surveillez les
null
valeurs pour PK IDla source
Ce problème m'est arrivé lorsque j'ai créé une nouvelle entité et une entité associée dans une méthode marquée comme
@Transactional
, puis effectué une requête avant d'enregistrer. ExPour corriger, j'ai effectué la requête avant de créer la nouvelle entité.
la source
à côté de toutes les autres bonnes réponses, cela peut se produire si vous utilisez
merge
pour conserver un objet et oubliez accidentellement d'utiliser la référence fusionnée de l'objet dans la classe parent. considérons l'exemple suivantDans ce cas, vous fusionnez
A
mais oubliez d'utiliser l'objet fusionné deA
. pour résoudre le problème, vous devez réécrire le code comme ceci.la source
j'obtiens cette erreur quand j'utilise
mais ça marche sans problème quand j'utilise
la source
J'ai également fait face à la même situation. En définissant l'annotation suivante au-dessus de la propriété, elle résout l'exception demandée.
L'exception que j'ai rencontrée.
Pour surmonter, l'annotation que j'ai utilisée.
Ce qui a poussé Hibernate à lever l'exception:
Cette exception est levée sur votre console car l'objet enfant que j'attache à l'objet parent n'est pas présent dans la base de données à ce moment.
En fournissant
@OneToMany(cascade = {CascadeType.ALL})
, il indique à Hibernate de les enregistrer dans la base de données tout en enregistrant l'objet parent.la source
Par souci d'exhaustivité: A
avec message
se produira également lorsque vous essayez de conserver / fusionner une entité avec une référence à une autre entité qui se trouve être détachée .
la source
Une autre raison possible: dans mon cas, j'essayais de sauver l'enfant avant de sauver le parent, sur une toute nouvelle entité.
Le code était quelque chose comme ça dans un modèle User.java:
La méthode setNewPassword () crée un enregistrement PasswordHistory et l'ajoute à la collection d'historique dans User. Étant donné que l'instruction create () n'avait pas encore été exécutée pour le parent, elle tentait de l'enregistrer dans une collection d'une entité qui n'avait pas encore été créée. Tout ce que j'avais à faire pour y remédier était de déplacer l'appel setNewPassword () après l'appel à create ().
la source
Il existe une autre possibilité qui peut provoquer cette erreur en veille prolongée. Vous pouvez définir une référence non enregistrée de votre objet
A
sur une entité attachéeB
et vouloir conserver un objetC
. Même dans ce cas, vous obtiendrez l'erreur susmentionnée.la source
Si vous utilisez Spring Data JPA, une
@Transactional
annotation supplémentaire à votre implémentation de service résoudrait le problème.la source
Je pense que c'est parce que vous avez essayé de faire persister un objet qui a une référence à un autre objet qui n'est pas encore persistant, et donc il essaie du "côté DB" de mettre une référence à une ligne qui n'existe pas
la source
Un moyen simple de résoudre ce problème consiste à enregistrer les deux entités. enregistrez d'abord l'entité enfant, puis enregistrez l'entité parent. Parce que l'entité parent dépend de l'entité enfant pour la valeur de clé étrangère.
Ci-dessous un simple examen d'une relation un à un
la source
Une cause possible de l'erreur est l'inexistence du réglage de la valeur de l'entité parent; Par exemple, pour une relation département-employés, vous devez écrire ceci afin de corriger l'erreur:
la source
Il y a tellement de possibilités de cette erreur, d'autres possibilités sont également sur la page d'ajout ou la page d'édition. Dans mon cas, j'essayais d'enregistrer un objet AdvanceSalary. Le problème est que lors de la modification, AdvanceSalary employee.employee_id est null car lors de la modification, je n'ai pas défini l'employé.employee_id. J'ai créé un champ caché et je l'ai défini. mon code fonctionne très bien.
la source
J'ai fait face à cette exception lorsque je n'ai pas persisté d'objet parent mais que je sauvais l'enfant. Pour résoudre le problème, avec dans la même session, j'ai persisté les objets enfant et parent et utilisé CascadeType.ALL sur le parent.
la source
Cas 1: J'obtenais cette exception lorsque j'essayais de créer un parent et d'enregistrer cette référence parent à son enfant, puis une autre requête DELETE / UPDATE (JPQL). Je viens donc de vider () l'entité nouvellement créée après avoir créé un parent et après avoir créé un enfant en utilisant la même référence parent. Cela a fonctionné pour moi.
Cas 2:
Classe parent
Classe enfant:
Dans le cas ci-dessus, où le parent (Reference) et l'enfant (ReferenceAdditionalDetails) ont une relation OneToOne et lorsque vous essayez de créer une entité Reference, puis son enfant (ReferenceAdditionalDetails), cela vous donnera la même exception. Donc, pour éviter l'exception, vous devez définir null pour la classe enfant, puis créer le parent. (Exemple de code)
la source
Mon problème était lié à
@BeforeEach
JUnit. Et même si j'ai enregistré les entités liées (dans mon cas@ManyToOne
), j'ai eu la même erreur.Le problème est en quelque sorte lié à la séquence que j'ai chez mes parents. Si j'attribue la valeur à cet attribut, le problème est résolu.
Ex. Si j'ai la question d'entité qui peut avoir certaines catégories (une ou plusieurs) et la question d'entité a une séquence:
Je dois assigner la valeur
question.setId(1L);
la source
Créez simplement Constructeur de votre mapping dans votre classe de base. Comme si vous voulez une relation un à un dans l'entité A, l'entité B. si vous prenez A comme classe de base, alors A doit avoir un constructeur avec B comme argument.
la source