Bonjour,

Je me trouve coincée sur un problème qui est probablement très simple, mais je ne trouve pas mon erreur
Je souhaite utiliser une liaison ManyToMany avec des colonnes supplémentaires. J'ai donc suivi ce chapitre de l'excellent Wikibook consacré à JPA.

Dans mon cas, j'ai une table "Photo" et une table "Defaut". Je souhaiterai lier les deux par une liaison du type ManyToMany, avec un champ supplémentaire qui décrirait le type de défaut de la photo.

J'ai donc créé les entités suivantes :
DBDefaut.java :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
@Entity
@Table(name="DEFAUT")
public class DBDefaut implements Serializable {
        private static final long serialVersionUID = 1L;
        @Id
        @TableGenerator(name="DefautIdGen",
                allocationSize=1, initialValue=1)
        @GeneratedValue(strategy = GenerationType.TABLE,
                generator="DefautIdGen")
        @Column(name="ID_DEFAUT")
        private Long id;
 
        @OneToMany(mappedBy="dbDefaut", cascade=CascadeType.PERSIST)
        private List<DBAssociation> dbPhotos;
 
        @Column(name="PERIMETRE")
        private double perimetre;
 
        public void addPhoto(DBPhoto dbPhoto, String type, String etat,
                long ordre) {
                DBAssociation association = new DBAssociation();
                association.setPhotoId(dbPhoto.getId());
                association.setDefautId(this.id);
                association.setDBDefaut(this);
                association.setDBPhoto(dbPhoto);
                association.setType(type);
 
                this.dbPhotos.add(association);
 
                dbPhoto.getDbDefauts().add(association);
        }
        [...]
}
DBPhoto.java :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
 
@Entity
@Table(name="PHOTO")
public class DBPhoto implements Serializable {
        private static final long serialVersionUID = 1L;
        @Id
        @TableGenerator(name="PhotoIdGen",
                allocationSize=1, initialValue=1)
        @GeneratedValue(strategy = GenerationType.TABLE,
                generator="PhotoIdGen")
        @Column(name="ID")
        private Long id;
 
        @OneToMany(mappedBy="dbPhoto", cascade=CascadeType.PERSIST)
        private List<DBAssociation> dbDefauts;
 
        @Column(name="PHOTO")
        private String photo;
 
        public void addDefaut(DBDefaut dbDefaut, String type, String etat,
                long ordre) {
                DBAssociation association = new DBAssociation();
                association.setDefautId(dbDefaut.getId());
                association.setPhotoId(this.id);
                association.setDBDefaut(dbDefaut);
                association.setDBPhoto(this);
                association.setType(type);
 
                this.dbDefauts.add(association);
 
                dbDefaut.getDbPhotos().add(association);
        }
        [...]
}
Mon entité d'association DBAssociation.java :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
 
@Entity
@Table(name = "DEFAUT_PHOTO")
@IdClass(DBAssociationId.class)
public class DBAssociation implements Serializable {
 
        private static final long serialVersionUID = 1L;
 
        @Id
        private Long defautId;
        @Id
        private Long photoId;
 
        @Column(name="TYPE")
        private String type;
 
        @ManyToOne
        @PrimaryKeyJoinColumn(name="ID_DEFAUT", referencedColumnName="ID_DEFAUT")
        private DBDefaut dbDefaut;
 
        @ManyToOne
        @PrimaryKeyJoinColumn(name="ID_PHOTO", referencedColumnName="ID_PHOTO")
        private DBPhoto dbPhoto;
 
        [...]
}
 
public class DBAssociationId implements Serializable {
        private static final long serialVersionUID = 1L;
 
        private Long defautId;
 
        private Long photoId;
 
        public DBAssociationId(Long defautId, Long photoId) {
                this.defautId = defautId;
                this.photoId = photoId;
        }
        [...]
}
Ensuite je laisse Netbeans se charger de la création des controllers.

Je ne sais pas si le problème vient de la déclaration de mes entités, ou bien de l'utilisation que j'en fais... Quand je veux créer des objets et les insérer dans ma base, je fais une requête comme ceci :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 
DBDefaut dBDefaut = new DBDefaut();
dBDefaut.setDbPhotos(new ArrayList<DBAssociation>());
 
DBPhoto dBPhoto = new DBPhoto();
dBPhoto.setDbDefauts(new ArrayList<DBAssociation>());
dBDefaut.addPhoto(dBPhoto, "type");
 
try {
	DBPhotoJpaController dBPhotoJpaController = new DBPhotoJpaController();
	dBPhotoJpaController.create(dBPhoto);
	DBDefautJpaController dBDefautJpaController = new DBDefautJpaController();
	dBDefautJpaController.create(dBDefaut);
} catch (Exception e) {
	IJ.log(e.toString());
}
Et enfin l'erreur que j'obtiens est la suivante :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
 
java.lang.IllegalArgumentException: An instance of a null PK has been incorrectly provided for this find operation.
Je comprends bien qu'à un moment, je dois faire quelque chose d'illégal avec les clés primaires... Mais je n'arrive pas à savoir d'où vient mon problème. Pourriez-vous m'éclairer?

Merci beaucoup