J'ai deux objets utilisateur et pendant que j'essaie de sauvegarder l'objet à l'aide de
session.save(userObj);
Je reçois l'erreur suivante:
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]
Je crée la session en utilisant
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
J'ai aussi essayé de faire la session.clear()
avant de sauvegarder, toujours pas de chance.
C’est pour la première fois que je reçois l’objet de session quand une requête de l’utilisateur arrive, alors je comprends pourquoi dit que cet objet est présent dans la session.
Aucune suggestion?
J'ai eu cette erreur à plusieurs reprises et il peut être assez difficile à localiser ...
En gros, hibernate dit que vous avez deux objets qui ont le même identifiant (même clé primaire) mais ne sont pas le même objet.
Je vous suggère de décomposer votre code, c'est-à-dire de commenter les bits jusqu'à ce que l'erreur disparaisse, puis de remettre le code en place jusqu'à ce qu'il revienne et vous devriez trouver l'erreur.
Cela se produit le plus souvent via des sauvegardes en cascade où il existe une sauvegarde en cascade entre les objets A et B, mais l'objet B a déjà été associé à la session, mais pas sur la même instance de B.
Quel générateur de clé primaire utilisez-vous?
La raison pour laquelle je pose cette question est que cette erreur est liée à la façon dont vous demandez à Hibernate de déterminer l’état persistant d’un objet (c’est-à-dire si un objet est persistant ou non). L'erreur peut se produire car hibernate tente de persister et un objet déjà persistant. En fait, si vous utilisez save, hibernate essaie de conserver cet objet, et peut-être existe-t-il déjà un objet avec la même clé primaire associée à la session.
Exemple
En supposant que vous ayez un objet de classe hibernation pour une table avec 10 lignes basées sur une combinaison de clés primaires (colonne 1 et colonne 2). Vous avez maintenant supprimé 5 lignes de la table à un moment donné. Maintenant, si vous essayez d'ajouter à nouveau les mêmes 10 lignes, alors qu'hibernate tente de conserver les objets dans la base de données, 5 lignes déjà supprimées seront ajoutées sans erreur. Maintenant, les 5 lignes restantes qui existent déjà lanceront cette exception.
Donc, l’approche facile consisterait à vérifier si vous avez mis à jour/supprimé une valeur dans une table qui fait partie de quelque chose et plus tard, essayez-vous d’insérer à nouveau les mêmes objets
Ceci est seulement un point où hibernate crée plus de problèmes qu'il n'en résout . Dans mon cas, de nombreux objets portent le même identifiant 0, car ils sont nouveaux et n'en ont pas. La base de données les génère. Quelque part, j'ai lu que 0 signal n'identifie pas. La façon intuitive de les persister est de les parcourir et de les mettre en veille prolongée pour sauver les objets. Mais vous ne pouvez pas faire cela - "Bien sûr, vous devriez savoir que l'hibernation fonctionne ceci et ainsi, vous devez donc ..." works . En fin de compte, il est plus facile de le faire avec un simple mappeur vous-même, car l'hibernation n'est qu'un fardeau intransparent supplémentaire . faire presque tous les travaux manuellement. Mais si vous devez le faire quand même, utiliser le mode veille prolongée ne représente qu'un travail supplémentaire.
USe session.evict(object);
La fonction de la méthode evict()
permet de supprimer une instance du cache de session. Donc, pour la première fois, en enregistrant l'objet, enregistrez-le en appelant la méthode session.save(object)
avant d'expulser l'objet du cache. De la même manière, mettez à jour l'objet en appelant session.saveOrUpdate(object)
ou session.update(object)
avant d'appeler evict ().
Cela peut se produire lorsque vous avez utilisé le même objet de session en lecture et en écriture. Comment? Supposons que vous ayez créé une session . Vous avez lu un enregistrement de la table employee avec la clé primaire Emp_id = 101 Vous avez maintenant modifié l'enregistrement en Java . Et vous allez enregistrer le Enregistrement d'employé dans la base de données ... Nous n'avons fermé la session nulle part ici ... puisque l'objet qui a été lu persiste également dans la session. Cela entre en conflit avec l'objet que nous souhaitons écrire. D'où cette erreur vient.
Comme quelqu'un l'a déjà indiqué ci-dessus, j'ai rencontré ce problème lorsque cascade=all
se trouvait aux deux extrémités d'une relation one-to-many
; supposons donc A -> B (un à plusieurs de A et plusieurs à un de B) et mettais à jour instance de B dans A puis appelant saveOrUpdate (A), il en résultait une demande de sauvegarde circulaire, c’est-à-dire que la sauvegarde de A déclenche la sauvegarde de B qui déclenche la sauvegarde de A ... et dans la troisième instance que l’entité (de A) était essayé d'être ajouté à la sessionPersistenceContext l'exception duplicateObject a été levée.
Je pourrais le résoudre en supprimant la cascade d'un bout.
J'ai aussi rencontré ce problème et j'ai eu du mal à trouver l'erreur.
Le problème que j'ai eu était le suivant:
L'objet a été lu par un Dao avec une session d'hibernation différente.
Pour éviter cette exception, relisez simplement l'objet avec le DAO qui va sauvegarder/mettre à jour cet objet ultérieurement.
alors:
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();
}
}
J'espère que cela fera gagner du temps à certaines personnes!
J'ai rencontré ce problème en:
Je l'ai résolu en vidant les résultats après la suppression et en effaçant le cache avant d'enregistrer le nouvel objet.
String delQuery = "DELETE FROM OasisNode";
session.createQuery( delQuery ).executeUpdate();
session.flush();
session.clear();
Obtenez l'objet à l'intérieur de la session, voici un exemple:
MyObject ob = null;
ob = (MyObject) session.get(MyObject.class, id);
J'ai rencontré ce problème avec la suppression d'un objet, ni l'expulsion ni clair aidé.
/**
* 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);
}
J'ai la même erreur que je remplaçais mon Set par un nouveau get de Jackson.
Pour résoudre ceci, je conserve l'ensemble existant, je supprime de l'ancien ensemble l'élément unknown dans la nouvelle liste avec retainAll
. J'ajoute ensuite les nouveaux avec addAll
.
this.oldSet.retainAll(newSet);
this.oldSet.addAll(newSet);
Pas besoin d'avoir la session et de la manipuler.
Le problème se produit parce que, dans la même session d'hibernation, vous essayez de sauvegarder deux objets avec le même identifiant. Il existe deux solutions: -
Cela se produit car vous n'avez pas configuré correctement votre fichier mapping.xml pour les champs d'ID, comme ci-dessous: -
<id name="id">
<column name="id" sql-type="bigint" not-null="true"/>
<generator class="hibernateGeneratorClass"</generator>
</id>
Surchargez la méthode getsession pour accepter un paramètre tel que isSessionClear, Et effacez la session avant de renvoyer la session en cours, comme ci-dessous.
public static Session getSession(boolean isSessionClear) {
if (session.isOpen() && isSessionClear) {
session.clear();
return session;
} else if (session.isOpen()) {
return session;
} else {
return sessionFactory.openSession();
}
}
Cela entraînera l'effacement des objets de session existants et même si hibernate ne génère pas d'identificateur unique, si vous avez correctement configuré votre base de données pour une clé primaire à l'aide de quelque chose comme Auto_Increment, cela devrait fonctionner pour vous.
il suffit de vérifier l'identifiant si cela prend nul ou 0 comme
if(offersubformtwo.getId()!=null && offersubformtwo.getId()!=0)
dans ajouter ou mettre à jour où le contenu est défini du formulaire à Pojo
@GeneratedValue (strategy = GenerationType.IDENTITY), l'ajout de cette annotation à la propriété de clé primaire de votre bean entity devrait résoudre ce problème.
Ce problème se produit lorsque nous mettons à jour le même objet de session, que nous avons utilisé pour extraire l'objet de la base de données.
Vous pouvez utiliser la méthode de fusion de hibernation au lieu de la méthode de mise à jour.
par exemple. Commencez par utiliser session.get (), puis par session.merge (objet). Cette méthode ne créera aucun problème. Nous pouvons également utiliser la méthode merge () pour mettre à jour un objet dans la base de données.
Autrement que ce quewbdarbya dit, cela peut même arriver quand un objet est récupéré en donnant l'identifiant de l'objet à un HQL. Si vous essayez de modifier les champs d’objet et de les sauvegarder dans la base de données (les modifications peuvent être insérées, supprimées ou mises à jour) au cours de la même session , cette erreur apparaîtra. Essayez de vider la session d'hibernation avant d'enregistrer votre objet modifié ou de créer une nouvelle session .
J'espère que j'ai aidé ;-)
Essaye ça. Le dessous a fonctionné pour moi!
Dans le fichier hbm.xml
Nous devons définir l'attribut dynamic-update
de la balise de classe sur true
:
<class dynamic-update="true">
Définissez l'attribut de classe de la balise générateur dans la colonne unique sur identity
:
<generator class="identity">
Remarque: définissez la colonne unique sur identity
plutôt que assigned
.
Vérifiez si vous avez oublié de mettre @GenerateValue pour la colonne @Id .J'ai eu le même problème avec plusieurs à plusieurs relations entre Film et Genre. Le programme a lancé Erreur Hibernate: org.hibernate.NonUniqueObjectException: un objet différent avec la même valeur d'identifiant était déjà associé à la session Erreur . J'ai découvert plus tard que je devais simplement m'assurer que vous aviez @GenerateValue à la méthode GenreId get.
NHibernate est un nouvel utilisateur. Le problème, c’est que j’ai utilisé une session différente pour interroger mon objet et pour l’enregistrer. Donc, la session de sauvegarde ne connaissait pas l'objet.
Cela semble évident, mais en lisant les réponses précédentes, je cherchais partout 2 objets, pas 2 sessions.
Les correspondances de vos identifiants sont-elles correctes? Si la base de données est responsable de la création de l'identifiant via un identifiant, vous devez mapper votre objet utilisateur sur cet identifiant.
avant de commencer à positionner les objets répétitifs, vous devez fermer la session .__ et commencer une nouvelle session
session.close();
session = HibernateUtil.getSessionFactory().openSession();
ainsi, de la sorte, dans une session, il n’existe pas plus d’une entité ayant le même identifiant.
J'avais un problème similaire. Dans mon cas, j'avais oublié de définir la valeur increment_by
dans la base de données de la même façon que celle utilisée par cache_size
et allocationSize
. (Les flèches indiquent les attributs mentionnés)
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
Java:
@SequenceGenerator(name = "mySG", schema = "my",
sequenceName = "my_id_seq", allocationSize = 20 <-)
Vous pouvez utiliser session.merge(obj)
, si vous effectuez une sauvegarde avec différentes sessions avec le même identifiant d'objet persistant.
Cela a fonctionné, j'avais même problème avant.
Vous pouvez vérifier vos paramètres de cascade. Cela pourrait être causé par les paramètres Cascade de vos modèles. J'ai supprimé les paramètres Cascade (n'autorisant pas les insertions/mises à jour Cascade) et cela a résolu mon problème.
Vous pouvez toujours faire une session flush . Flush synchronisera l'état de tous vos objets en session (s'il vous plaît, corrigez-moi si je me trompe), et cela résoudrait peut-être votre problème dans certains cas.
Implémenter vos propres égaux et hashcode peut également vous aider.
J'ai résolu un problème similaire comme celui-ci:
plan = (FcsRequestPlan) session.load(plan.getClass(), plan.getUUID());
while (plan instanceof HibernateProxy)
plan = (FcsRequestPlan) ((HibernateProxy) plan).getHibernateLazyInitializer().getImplementation();
Est-ce que cela aide?
User userObj1 = new User();
User userObj2 = userObj1;
.
.
.
rtsession.save(userObj1);
rtsession.save(userObj2);
Une autre chose qui a fonctionné pour moi a été de rendre la variable d'instance Long au lieu de long
J'ai eu ma variable principale primaire long id; Le changer en Long id; travaillé
Bonne chance
J'ai résolu ce problème.
En fait, cela se produit car nous avons oublié l'implémentation de la propriété Generator Type of PK dans la classe de haricot. Alors faites-en n'importe quel type comme
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
quand nous persistons les objets de bean, chaque objet a acquis le même ID, donc le premier objet est enregistré, lorsqu'un autre objet persiste, puis HIB FW via ce type de Exception: org.hibernate.NonUniqueObjectException:
, un objet différent avec le même identifiant a déjà été associé à la session.
En retard à la fête, mais peut aider pour les utilisateurs à venir -
J'ai eu ce problème lorsque je sélectionnez un enregistrement en utilisant getsession()
et encore update un autre enregistrement avec le même identifiant en utilisant même session provoque le problème. Code ajouté ci-dessous.
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
Cela ne devrait jamais être fait. La solution consiste à expulser la session avant la mise à jour ou à modifier la logique métier.
Une solution de contournement pour résoudre ce problème consiste à essayer de relire l'objet à partir de hibernate cache/db avant d'effectuer toute mise à jour, puis de persister.
Exemple:
OrderHeader oh = orderHeaderDAO.get(orderHeaderId);
oh.setShipFrom(facilityForOrder);
orderHeaderDAO.persist(oh);
Remarque: Gardez à l'esprit que cela ne résout pas la cause première mais résout le problème.
J'ai trouvé cette erreur aussi. Ce qui a fonctionné pour moi est de m'assurer que la clé primaire (générée automatiquement) n'est pas un PDT (c'est-à-dire long, int, ect.), Mais un objet (c'est-à-dire long, Integer, etc.)
Lorsque vous créez votre objet pour le sauvegarder, assurez-vous de passer null et non 0.