2009-06-03 6 views
5

Mon équipe a deux classes, User et Store, liées par JPA @ManyToMany annotations. Le code pertinent est ci-dessous.JPA @ManyToMany Ecrire sur créer mais pas mettre à jour

Lors de la création d'un nouvel objet User et de définir ses magasins, la vie est bonne. Mais nous constatons un comportement inattendu lorsque nous essayons de mettre à jour les objets Utilisateur via notre interface utilisateur Web Struts 2/Spring. (Ces problèmes ne se produisent pas lors de l'exécution de tests d'intégration automatisés simples via JUnit). En d'autres termes, lors de l'enregistrement d'un User, sa collection de magasins n'est pas mise à jour. La base de données n'indique aucune modification et les rechargements de l'objet User en question indiquent qu'il s'agit d'un ensemble de magasins inchangé.

La seule solution que nous avons trouvée à ce problème - et nous n'aimons pas cette solution, cela rend un peu mal à l'aise tous les développeurs de notre équipe - est de créer un nouveau Set de Store s, puis faites user.setStores(null), puis faites user.setStores(stores). Nous employons le OpenEntityManagerInViewFilter; nous utilisons Hibernate comme fournisseur JPA; nous utilisons JpaTransactionManager de Spring. Nous n'avons aucune @Transactional annotations dans notre code - et leur ajout brise le code existant en raison du comportement du proxy décrit ailleurs.

Tout renseignement que vous pourriez nous donner sur la façon dont nous pourrions résoudre ce problème de manière non-malodorante est le bienvenu.


partie pertinente du User.java:

@ManyToMany 
@JoinTable(name = "company.user_store_access", 
     joinColumns = @JoinColumn(name = "userid"), 
     inverseJoinColumns = @JoinColumn(name = "storeid")) 
public Set<Store> getStores() { 
    return stores; 
} 

partie pertinente du Store.java:

@ManyToMany(mappedBy = "stores") 
    public List<User> getUsers() { 
     return users; 
    } 

parties pertinentes de UserDetailAction.java: (pass-through vers le bas une couche ou deux, et ensuite :)

entity = getEntityManager().merge(entity); 
+1

Pourriez-vous s'il vous plaît ajouter les lignes de code où vous ajoutez/modifiez des magasins? –

Répondre

1

S'il vous plaît essayez l'annotation suivante dans votre objet utilisateur:

@ManyToMany(cascade = {CascadeType.ALL}) 
+0

Je vais essayer le matin - même si nous avons déjà ajouté @ManyToMany (cascade = {CascadeType.PERSIST, CascadeType.MERGE}) déjà. –

6

Le problème est que vous avez une relation bidirectionnelle, et dans ce cas il y a une entité qui contrôle l'autre, et de votre cartographie du contrôle l'un est le Store entité et non le Utilisateur, donc l'ajout d'un utilisateur à un magasin fonctionnerait (puisque le magasin est celui qui contrôle) mais l'ajout d'un magasin à un utilisateur ne fonctionnera pas. Essayez d'inverser la situation, en faisant de l'objet User celui qui contrôle la relation, en mettant l'annotation @ManyToMany (mappedBy = "users") sur la méthode getStores() et en changeant celle de getUsers().

J'espère que cela a aidé.

P.S. l'entité qui contrôle la relation est toujours celle qui n'a pas l'attribut mappedBy.

2

Je me suis juste coincé au même problème et trouvé la solution sur une autre page.

Voici ce qui a fonctionné pour moi

appelant getJpaTemplate() flush(). Avant d'appeler fusion a travaillé pour moi.

Je n'ai pas compris la raison pour laquelle cela a fonctionné.

Questions connexes