10
votes

L'insertion hibernate à une collection provoque une suppression alors tous les éléments de la collection à insérer à nouveau

J'ai beaucoup à faire de la relation de cohorps et d'employé. Chaque fois que j'insère un employé dans le groupe Hibernate de CohortGroup supprime le groupe de la table de résolution et insère à nouveau tous les membres, plus le nouveau. Pourquoi ne pas simplement ajouter le nouveau?

L'annotation dans le groupe: xxx

l'autre côté de l'employé xxx

code snipit xxx

ci-dessous est le SQL signalé dans le journal xxx

cette couture vraiment inefficace et causant quelques problemes. Si des demandes de Sevral sont prises pour ajouter un employé au groupe, des quelques-là ont été écrites.

Les coutures comme des égaux et des hachages pourraient être une raison pour cela. Vous trouverez ci-dessous la mise en œuvre de ces méthodes. Tous les drapeaux rouges?

cohortgroup xxx

employé xxx

J'ai ajouté une méthode addmember Le groupe cohort qui ajoute aux deux côtés de la relation: xxx

suite grâce à tout ce qui aide.


3 commentaires

Oui j'ai le même comportement. Je viens d'apprendre à vivre avec ça :-) Cela arrive lorsque vous définissez une liste / définie sur une clé étrangère


Alors, que faites-vous pour vivre avec ça? Ralentissez l'interface utilisateur pour éviter de se produire. J'ai une application Ajax pouvant tirer sur cette demande aussi vite que l'utilisateur peut cliquer sur. Cela provoque des fautes intermittentes sur les inserts.


J'avais plus ou moins le même problème ... avoir la foi! Stackoverflow.com/Questtions/179259


7 Réponses :


0
votes

Vous devez définir hashcode () et égale () sur votre cohortgroup et employé Employé. Cela peut être fait automatiquement par votre IDE et peut être sur la clé primaire (parfois pas une bonne idée) ou sur une clé d'entreprise (préférable).

Lire Cet article .


1 commentaires

Merci pour le lien avec l'article, il aide



7
votes

Je soupçonne fortement que vous ne remplacez pas égale et hashcode correctement. Les déroberts à tort peuvent entraîner le type de comportement que vous rencontrez (car la touche HASH est utilisée comme des clés dans les cartes). Vérifiez ce que vous avez fait avec égale et hashcode .

Utilisation vos entités annotées avec un bon est égal à et < Code> hashcode , ce code (logiquement équivalent): xxx

produit la sortie suivante sur ma machine: xxx

pas de suppression avant l'insertion!

D'aillie, notez que vous devez définir le lien sur côtés lorsque vous travaillez avec des associations bidirectionnelles, comme je l'ai fait sur le Groupe et sur l'employé.

ou ajoutez des méthodes de gestion de liaison défensive sur vos classes, par exemple sur cohortgroup : xxx


5 commentaires

Je vais vérifier le code de hachage et les égaux. Ils sont mis en œuvre, je viens d'avoir Eclipse les créer pour moi. Si cela ne fait pas l'affaire, je vais commencer vos autres recommandations. Je posterai mes résultats pour la prospérité.


Je suis à peu près sûr que j'ai le hashcode et que les égaux sont mis en œuvre correctement, mais le comportement reste. La première fois qu'un groupe a ajouté et employé il n'y a pas de suppression. Cela arrive simplement s'il y a déjà plus d'un autre employé du groupe. Je ne sais pas si votre test a ajouté un employé à un groupe qui avait déjà des employés ou non.


Pascal, merci d'avoir aidé. Si je veux montrer le hashcode et équiper des méthodes où puis-je poster cela? Comme réponse à cette question ou éditer celui ci-dessus?


@Mark Il est préférable de modifier votre question. Utilisez des réponses pour répondre.


J'ai mis un système.out dans les égaux et la méthode HashCode. Rien n'est jamais imprimé lorsqu'un insert est effectué. Cela signifie-t-il que je regarde au mauvais endroit pour le problème?



1
votes

Comme d'autres ont suggéré, c'est probablement un problème avec hashcode ou égale .

Plus précisément: les proxy d'hibernation causent des problèmes avec Instaceof que vous utilisez dans votre est égal à la méthode . Cela sortira de mauvaises nouvelles.

Vérifiez ceci: http://community.jboss.org/wiki/proxyVisitorpattern


4 commentaires

Modifierait la méthode des égaux pour effectuer une comparaison de la classe getname (this.getclass (). GetName (). Équals (autre.getClass (). GetName ()) Complétez le problème ou affichez-vous à changer d'utilisation Le modèle de visiteur pour récupérer ces listes?


Aucune modification de la méthode ne fonctionnera. Parce que les classes proxées ont des noms amusants. Une chose que vous pouvez faire est d'ajouter une méthode comme si classe publique getClass () {retour this.getclass (); } . Lorsque vous appelez getclass sur le proxy, vous obtenez la classe du proxy. Lorsque vous appelez getClass il déléguette à votre classe "réelle". Type de hack par rapport au visiteur.


Je ne devrais-je pas ajouter quelques vérifications pour que la méthode existait avant de l'appeler? La raison pour laquelle les égaux font une instanceOF est de s'assurer qu'il est prudent de lancer l'objet transmis. Je ne comprends donc pas comment le getClass fonctionnerait quand appelé à partir de la méthode des égaux ou de l'option de visiteur est toujours le meilleur candidat à explorer.


Les objets que j'utilise ne sont pas des sous-classes de rien. Ils mettent en œuvre certaines interfaces mais elles ne prolongent rien. Si je comprends ce que je lis, ce n'est probablement pas la cause "très sympa dans des cas simples sans hiérarchie d'objets. La typé de l'objet et l'instance de travail fonctionnent parfaitement sur le proxy dans ce cas car il s'agit d'une sous-classe directe."



0
votes

J'ai des insertions agissant comme je l'attends maintenant. Merci à Pascal et à Z5H, j'ai beaucoup appris. Je crois que j'ai le hashcode et les égaux mis en œuvre correctement. Cela n'a jamais résolu le problème pour moi cependant. Au lieu de cela, j'ai mis en place une entité intermédiaire.

Pour ce que cela vaut ci-dessous, vous trouverez la cartographie de mon employé, Cohorgroup et maintenant CohortGroupMemeber classes. P>

Employee: P>

@OneToMany(mappedBy="group")
public List<CohortGroupMember> getMembers(){
    return members;
}
public void setMembers(List<CohortGroupMember> emps){
    members = emps;
}


2 commentaires

Bien que ce soit une solution. La meilleure solution consiste à utiliser un ensemble au lieu d'une liste. Voir l'article que j'ai lié à la réponse de Marc pour la raison pour laquelle.


@Justinksu merci mec, j'apprécie vraiment cet article !!! Vous pouvez toujours apprendre quelque chose de nouveau sur hibernate :)



5
votes

J'ai eu le même problème et que certains essais et erreurs ont révélé que les suppressions ne se sont pas produites si j'avais utilisé un ensemble au lieu d'une liste comme ma collection. Irritant, étant donné que j'utilise JSF et que les composants de l'interface utilisateur ne feront que itération sur les listes. Mais là c'est.


2 commentaires

C'est la racine du problème. Lisez Assarconsulting.blogspot.com/2009 / 08 / ... pour plus de détails.


-1 parce que j'ai vécu le même problème avec des ensembles. Votre réponse aidera toute personne qui entretient l'entité définie dans une session hibernate et peut donc s'appuyer sur l'identité de Java standard (==). Toutefois, entre deux sessions hibernées, les ensembles afficheront le même problème que les listes. Le problème se résume à la mise en oeuvre correctement des égaux et du hashcode.



0
votes

Chargez l'objet dans le contexte de la persistance et appelez la fusion si existez et enregistrez-le s'il n'existe pas.

Employee emp = new Employee();
//set emp attribute and members.
Session session = ...
Transaction transaction = ...
Employee db = (Employee) session.get(Employee .class,emp.getId());
if(db != null)  session.merge(emp);
else  session.save(emp);
/*session.saveOrUpdate(emp); This will delete the join table and reinsert entry  
again*/
transaction.commit();
session.close();


0 commentaires

1
votes

J'ai le même problème. J'ai changé de liste à définir. Cela fonctionne pour moi.

@ManyToMany(cascade = { PERSIST, MERGE, REFRESH })
@JoinTable(name="MYSITE_RES_COHORT_GROUP_STAFF",
joinColumns={@JoinColumn(name="COHORT_GROUPID")},
inverseJoinColumns={@JoinColumn(name="USERID")})
public Set<Employee> getMembers(){
  return members;
}

@ManyToMany(mappedBy="members",cascade = { PERSIST, MERGE, REFRESH } )
public Set<CohortGroup> getMemberGroups(){
  return memberGroups;
}


0 commentaires