2015-12-02 1 views
0

Je travaille sur une application web fonctionnant sous GlassFish 4.1.1, utilisant EclipseLink 2.6.1. J'ai une relation ManyToMany unidirectionnelle entre les utilisateurs et les projets, et lorsque je supprime des éléments de User.projects et fusionne l'utilisateur, les lignes de jointure ne sont pas supprimées dans la base de données. J'ai fait une petite application de démonstration pour l'isoler:JPA Unidirectionnel ManyToMany impossible à supprimer

classe User:

@Entity 
@Table(name = "demouser") 
public class DemoUser implements Serializable { 
    @Id 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "DemoUserSeq") 
    @SequenceGenerator(name = "DemoUserSeq", sequenceName = "demouser_userid_seq", allocationSize = 1) 
    @Column(name = "userid") 
    private Integer id; 
    @Column(name = "username") 
    private String userName; 
    // some more fields 
    @JoinTable(name = "demouserprojbind", joinColumns = { 
     @JoinColumn(name = "username", referencedColumnName = "username") 
    }, inverseJoinColumns = { 
     @JoinColumn(name = "projcode", referencedColumnName = "projcode") 
    }) 
    @ManyToMany 
    private Set<DemoProject> projects; 

DemProject n'a pas un ManyToMany mis en correspondance avec les utilisateurs. La table de liaison "demouserprojbind" se lie aux colonnes de texte uniques (not-null) au lieu des PK série.

Code de mise à jour de démonstration:

DemoUser user = getUser(username); // EntityManager Query by username 
Set<DemoProject> userProjects = user.getProjects(); 
userProjects.clear(); 
EntityManager em = emf.createEntityManager(); 
utx.begin(); 
em.joinTransaction(); 
em.merge(user); 
em.flush(); 
utx.commit(); 
em.close(); 

C'est un code de démonstration faite dans un Servlet - fem et UTX et injecté EntityManagerFactory et UserTransaction.

Lorsque je trace SQL de EclipseLink, il ressemble à ceci:

DELETE FROM demouserprojbind WHERE ((projcode = ?) AND (username = ?)) 
bind => [Project2, null] 
DELETE FROM demouserprojbind WHERE ((projcode = ?) AND (username = ?)) 
bind => [Project1, null] 

Il est apparemment incapable de mettre le nom d'utilisateur de l'entité propriétaire - SQL correspond à aucune ligne, et donc pas de lignes sont supprimés de la base de données.

Y a-t-il quelque chose qui ne va pas dans ma logique de sauvegarde (je veux supprimer la liaison entre un utilisateur et un projet, mais l'utilisateur et le projet doivent rester) ou est-ce un bogue dans EcliseLink?

+0

Est-ce la seule chose qui ne fonctionne pas, et ne vous avez des personnalisations sur la cartographie, ou des événements sur l'entité? JPA n'autorise pas l'utilisation de champs non pk dans les relations et, bien qu'il soit pris en charge par la plupart des fournisseurs (EclipseLink le permet), il provoque des problèmes de mise en cache et génère généralement des avertissements. Vérifiez que certains événements ne sont pas déclenchés pour définir userName = null ou que vous n'avez pas modifié une instance en lecture seule de telle sorte qu'une requête pour ce nom d'utilisateur renvoie une entité corrompue à partir du cache. – Chris

Répondre

0

Dans votre

@ManyToMany 
private Set<DemoProject> projects; 

Mettre dans le anotation ManyToMany type en cascade, comme ceci:

@ManyToMany(cascade={CascadeType.MERGE, CascadeType.REMOVE }) 
private Set<DemoProject> projects; 
+0

Mon code de démo avait réellement "(cascade = CascadeType.ALL)", et le réglage à (cascade = {CascadeType.MERGE, CascadeType.REMOVE}) n'a pas amélioré la situation. – thomjah