2012-07-13 6 views
1

Je travaille actuellement sur une application web utilisant Java EE/EclipseLink et postgreSQL. A propos de mes entités, je gère notamment "Projet", "Utilisateur" et "Droit" (droits d'accès comme lire, écrire, supprimer ...). La relation entre ces entités est la suivante: un projet peut avoir plusieurs utilisateurs qui ont des droits différents sur le projet. Par conséquent, j'ai une triple association: Projet + Utilisateur + Droit.Association triple de persistance JPA/EclipseLink

Je suis confronté à un problème gênant pendant la persistance de cette association. Quand je persiste un projet avec ses informations, tout va bien (c'est dans la DB et je peux l'utiliser dans mon application), j'ai aussi des droits et des utilisateurs persistants. Ensuite, je veux ajouter une association entre eux afin que je crée l'entité d'association appelée ProjectUserRight, je mis le projet, l'utilisateur et le droit des entités existantes, mais quand je persiste, je reçois l'exception ci-dessous:

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is javax.persistence.RollbackException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.DatabaseException 
Internal Exception: org.postgresql.util.PSQLException: ERREUR: une valeur NULL viole la contrainte NOT NULL de la colonne « id_project » 
Error Code: 0 
Call: INSERT INTO project_user_right (id_right, id_project, id_user) VALUES (?, ?, ?) 
bind => [3 parameters bound] 
Query: InsertObjectQuery([email protected]) 

Voici le projet de classe:

@Entity 
@Table(name="project") 
public class Project implements Serializable { 
private static final long serialVersionUID = 1L; 

@Id 
@GeneratedValue(strategy=GenerationType.IDENTITY) 
@Column(name="id_project", unique=true, nullable=false) 
private Integer idProject; 


    //bi-directional many-to-one association to ProjectUserRight 
@OneToMany(mappedBy="project", cascade={CascadeType.ALL}) 
private Set<ProjectUserRight> projetUtilDroits; 


    ... 

la classe utilisateur:

@Entity 
@Table(name="user") 
public class User implements Serializable { 
private static final long serialVersionUID = 1L; 

@Id 
@GeneratedValue(strategy=GenerationType.IDENTITY) 
@Column(name="id_user", unique=true, nullable=false) 
private Integer idUser; 


@Column(name="nom_utilisateur", nullable=false, length=50) 
private String userName; 

    //bi-directional many-to-one association to ProjectUserRight 
@OneToMany(mappedBy="user") 
private Set<ProjectUserRight> projetUtilDroits; 

    ... 

la classe A droite:

@Entity 
    @Table(name="right") 
    public class Right implements Serializable { 
private static final long serialVersionUID = 1L; 

@Id 
@GeneratedValue(strategy=GenerationType.IDENTITY) 
@Column(name="id_right", unique=true, nullable=false) 
private Integer idRight; 

@Column(name="type_right", nullable=false, length=10) 
private String typeRight; 

//bi-directional many-to-one association to ProjectUserRight 
@OneToMany(mappedBy="right") 
private Set<ProjectUserRight> projetUtilDroits; 

    ... 

Et la classe d'association:

@Entity 
@Table(name="project_user_right") 
public class ProjectUserRight implements Serializable { 
private static final long serialVersionUID = 1L; 

@EmbeddedId 
private ProjectUserRightPK id; 

//bi-directional many-to-one association to Right 
    @ManyToOne(cascade={CascadeType.MERGE, CascadeType.REFRESH}) 
@JoinColumn(name="id_right", insertable=false, updatable=false) 
private Right right; 

//bi-directional many-to-one association to Project 
@ManyToOne(cascade={CascadeType.MERGE, CascadeType.REFRESH}) 
@JoinColumn(name="id_project", insertable=false, updatable=false) 
private Project project; 

//bi-directional many-to-one association to User 
@ManyToOne(cascade={CascadeType.MERGE, CascadeType.REFRESH}) 
@JoinColumn(name="id_user", insertable=false, updatable=false) 
private User user; 

Et le ProjectUserRightPK (édité après commentaire):

@Embeddable 
public class ProjectUserRightPK implements Serializable { 
//default serial version id, required for serializable classes. 
private static final long serialVersionUID = 1L; 

@Column(name="id_project", unique=true, nullable=false) 
private Integer idProject; 

@Column(name="id_right", unique=true, nullable=false) 
private Integer idRight; 
    ...//getters and setters 
@Column(name="id_user", unique=true, nullable=false) 
private Integer idUser; 

j'ai écrit le code suivant pour persister l'association:

Project project = getService(Projet.class).getFromID(projectId);//retrieve the existing project from database with id 

User user = getService(Utilisateur.class).getFromID(userId);//retrieve the existing user from database with id 

Right right = getService(Right.class).getFromID(rightId);//retrieve the existing right from database with id 
if(project !=null && user!=null && right!=null){ 
    ProjectUserRight pud = new ProjectUserRight(); 
    pud.setRight(right); 
    pud.setProject(project); 
    pud.setUser(user); 
    project.getProjectUserRights().add(pud); 
    right.getProjectUserRights().add(pud); 
    user.getProjectUserRights().add(pud); 
    service(ProjetUtilDroit.class).persist(pud);//call the persist function on this entity (works fine with all other entities) 
    } 

J'ai également essayé de fusionner le projet au lieu de persister l'association, mais je ge t la même erreur ... (J'ai aussi vérifié le projet id et il est correctement réglé) Je me demande si c'est l'association qui est mal annotée mais je ne trouve pas la bonne façon de la changer. Donc, j'ai vraiment besoin de votre aide! :-)

Merci d'avance pour vos conseils!

+0

S'il vous plaît ajouter la définition de la classe ProjectUserRightPK –

+0

Fait! En effet, je dois admettre que je n'ai pas regardé dans cette classe en profondeur ... Merci pour votre aide – Coralie

Répondre

1

Vous avez manqué l'annotation @MapsId:

Désigne un ManyToOne ou d'une relation OneToOne attribut fournit le mappage pour une clé primaire EmbeddedId, un attribut dans une clé primaire EmbeddedId, ou une simple clé primaire de la entité parente. L'élément value spécifie l'attribut dans une clé composite à laquelle correspond l'attribut de relation.

@MapsId("idRight") 
@ManyToOne(cascade={CascadeType.MERGE, CascadeType.REFRESH}) 
@JoinColumn(name="id_right") 
private Right right; 

@MapsId("idProject") 
@ManyToOne(cascade={CascadeType.MERGE, CascadeType.REFRESH}) 
@JoinColumn(name="id_project") 
private Project project; 

@MapsId("idUser") 
@ManyToOne(cascade={CascadeType.MERGE, CascadeType.REFRESH}) 
@JoinColumn(name="id_user") 
private User user; 
+0

Ça marche !!! Merci beaucoup je n'avais jamais vu cette annotation auparavant, donc je n'aurais pas trouvé la solution sans votre aide! Merci encore! – Coralie