Bonjour,
j'ai une entité Membre, et une entité QuestionnaireReduit. Les deux sont liées par une association ManyToMany implémentée par une entité ListeQuestionnaire avec une clé composite.
Je me suis appuyée sur le tuto de Serge Tahé pour aboutir aux différentes classes en utilisant une classe Embeddable pour la clé composite.
J'ai créé des Dao pour ces trois entités. Aucun problème pour Membre et pour QuestionnaireReduit, par contre lors des tests unitaires du Dao de ListeQuestionnaire, j'obtiens l'erreur suivante :
Le truc, c'est que je ne sais pas si ça vient de mon implémentation du Dao, ou si ça vient de l'entité elle même... et mes recherches sur le forum et sur le net m'ont pas vraiment aidé.
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58 javax.persistence.EntityNotFoundException: Unable to find fr.statlife.protoE4N.data.entites.Membre with id ben.joris at org.hibernate.ejb.Ejb3Configuration$Ejb3EntityNotFoundDelegate.handleEntityNotFound(Ejb3Configuration.java:132) at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:233) at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:285) at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:152) at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:1080) at org.hibernate.impl.SessionImpl.internalLoad(SessionImpl.java:1028) at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:623) at org.hibernate.type.EntityType.resolve(EntityType.java:431) at org.hibernate.type.EntityType.replace(EntityType.java:291) at org.hibernate.type.AbstractType.replace(AbstractType.java:177) at org.hibernate.type.TypeFactory.replace(TypeFactory.java:583) at org.hibernate.event.def.DefaultMergeEventListener.copyValues(DefaultMergeEventListener.java:600) at org.hibernate.event.def.DefaultMergeEventListener.mergeTransientEntity(DefaultMergeEventListener.java:337) at org.hibernate.event.def.DefaultMergeEventListener.entityIsTransient(DefaultMergeEventListener.java:303) at org.hibernate.event.def.DefaultMergeEventListener.entityIsDetached(DefaultMergeEventListener.java:464) at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:255) at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:84) at org.hibernate.impl.SessionImpl.fireMerge(SessionImpl.java:859) at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:843) at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:847) at org.hibernate.ejb.AbstractEntityManagerImpl.merge(AbstractEntityManagerImpl.java:682) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:365) at $Proxy26.merge(Unknown Source) at fr.statlife.protoE4N.data.dao.jpa.AbstractDaoJPAImpl.saveOne(AbstractDaoJPAImpl.java:43) at fr.statlife.protoE4N.data.dao.jpa.TestListeQuestionnaireDao.startTransaction(TestListeQuestionnaireDao.java:50) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:27) at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74) at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:82) at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:240) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184) at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61) at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70) at org.junit.runners.ParentRunner.run(ParentRunner.java:236) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:180) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Cela dit, vu l'erreur, je penche plus vers un problème dans le Dao.
En fait, j'utilise une classe abstraite générique implémentant mon interface Dao :
et chacun de mes Dao étends cette classe. Ce qui donne pour ListeQuestionnaire :
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 public abstract class AbstractDaoJPAImpl<T extends DomainObject> implements Dao<T> { private Class<T> domainClass; @PersistenceContext(type=PersistenceContextType.EXTENDED) private EntityManager em; public AbstractDaoJPAImpl(Class<T> domainClass) { this.domainClass = domainClass; } public void deleteOne(T object) { em.remove(object); } public T getOne(Serializable id) { return (T) em.find(domainClass, id); } public T saveOne(T object) { return em.merge(object); } /* * Getters and setters */ public EntityManager getEm() { return em; } public void setEm(EntityManager em) { this.em = em; } }
Voici la classe de test :
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 @Repository public class ListeQuestionnaireDaoImpl extends AbstractDaoJPAImpl<ListeQuestionnaire> implements ListeQuestionnaireDao { public ListeQuestionnaireDaoImpl(){ super(ListeQuestionnaire.class); } public List<ListeQuestionnaire> findAll() { TypedQuery<ListeQuestionnaire> query = getEm().createQuery("select listeQ from ListeQuestionnaire listeQ", ListeQuestionnaire.class); return query.getResultList(); } public int countAll() { TypedQuery<Long> query = getEm().createQuery("select count(listeQ) from ListeQuestionnaire listeQ", Long.class); return (query.getSingleResult()).intValue(); } }
l'erreur apparait lors du listeQuestionnaire = listeQuestionnaireDao.saveOne(listeQuestionnaire); à chaque appel de la méthode startTransaction.
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("TestDao-context.xml") @DirtiesContext public class TestListeQuestionnaireDao { @Autowired private ListeQuestionnaireDao listeQuestionnaireDao; @Autowired private MembreDao membreDao; @Autowired private QuestionnaireReduitDao qReduitDao; private ListeQuestionnaire listeQuestionnaire; @Before public void startTransaction() throws ParseException{ Membre benji = new Membre(); benji.setIdMembre("ben.joris"); benji = membreDao.saveOne(benji); QuestionnaireReduit qReduit = new QuestionnaireReduit(); qReduit = qReduitDao.saveOne(qReduit); listeQuestionnaire = new ListeQuestionnaire(benji, qReduit); listeQuestionnaire.setaRepondu(false); listeQuestionnaire = listeQuestionnaireDao.saveOne(listeQuestionnaire); } @Test @Transactional @Rollback public void testFindAll() { List<ListeQuestionnaire> qReduitsAttendus = new ArrayList<ListeQuestionnaire>(); qReduitsAttendus.add(listeQuestionnaire); Assert.assertEquals(qReduitsAttendus, listeQuestionnaireDao.findAll()); } @Test @Transactional @Rollback public void testCountAll() { Assert.assertEquals(1, listeQuestionnaireDao.countAll()); } @Test @Transactional @Rollback public void testDelete() { listeQuestionnaireDao.deleteOne(listeQuestionnaire); Assert.assertEquals(0, listeQuestionnaireDao.countAll()); } @Test @Transactional @Rollback public void testLoad() { ListeQuestionnaire qReduit2 = listeQuestionnaireDao.getOne(listeQuestionnaire.getId()); Assert.assertEquals(listeQuestionnaire, qReduit2); } @Test @Transactional @Rollback public void testSave() { //if we have got this far then save works } }
ça fait un moment que je bloque sur cette erreur, alors j'étudierai la moindre piste !
au cas où ça pourrait aider, voici le code des trois entités :
Membre :
QuestionnaireReduit:
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 @Entity public class Membre extends DomainObject { private static final long serialVersionUID = -80426809311125204L; @Id private String idMembre; @Temporal(TemporalType.DATE) private Date dateNaissance; private Character sexe; private String password; private String codeIdentification; @OneToOne(cascade=CascadeType.ALL, fetch=FetchType.LAZY) @JoinColumn(unique=true, nullable=true) private InfosPerso infosPerso; //Getters and Setters }
et surtout ListeQuestionnaire :
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 @Entity public class QuestionnaireReduit extends DomainObject { private static final long serialVersionUID = 6829338996989112101L; @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long idQuestionnaireReduit; private String numero; private String titre; private Character sexeDestinataire; /* * Getters and setters */ }
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88 @Entity public class ListeQuestionnaire extends DomainObject { private static final long serialVersionUID = -6692608372646294912L; //clé primaire composite @EmbeddedId private Id id = new Id(); /* * Pour les deux attributs suivant, on fait le lien entre l'attribut et sa colonne dans la table * via l'annotation @JoinColumn * les propriétés (insertable=false, updatable=false) spécifient que JPA ne doit pas gérer ces clés * étrangères car c'est fait directement dans par l'application via le constructeur */ @ManyToOne @JoinColumn(name="idMembre", insertable=false, updatable=false) private Membre membre; @ManyToOne @JoinColumn(name="idQuestionnaireReduit", insertable=false, updatable=false) private QuestionnaireReduit questionnaireReduit; private Boolean aRepondu; /* * Constructeurs */ public ListeQuestionnaire(){ } public ListeQuestionnaire(Membre membre, QuestionnaireReduit questionnaireReduit) { //On fixe les clés étrangères getId().setIdMembre(membre.getIdMembre()); getId().setIdQuestionnaireReduit(questionnaireReduit.getIdQuestionnaireReduit()); //Associations bidirectionnelles this.membre = membre; this.questionnaireReduit = questionnaireReduit; } /** * Classe définissant la clé primaire composite */ @Embeddable public static class Id implements Serializable{ private static final long serialVersionUID = 1L; //Composantes de la clé primaire composite @Column(name="idMembre") private String idMembre; @Column(name="idQuestionnaireReduit") private Long idQuestionnaireReduit; /* * Getters and Setters */ public String getIdMembre() { return idMembre; } public void setIdMembre(String idMembre) { this.idMembre = idMembre; } public Long getIdQuestionnaireReduit() { return idQuestionnaireReduit; } public void setIdQuestionnaireReduit(Long idQuestionnaireReduit) { this.idQuestionnaireReduit = idQuestionnaireReduit; } /* * (non-Javadoc) * @see java.lang.Object#toString() */ @Override public String toString() { return "Id [idMembre=" + idMembre + ", idQuestionnaireReduit=" + idQuestionnaireReduit + "]"; } } /* * Getters and Setters */ }
Partager