Bonjour,
ça fait quelques jours que j'essaie d'implémenter une relation manyToMany porteuse d'information. Au final, j'ai utilisé la solution proposée par ce tuto : un POJO par entité (Membre, Questionnaire et ListeQuestionnaire dans mon cas) plus une entité pour la clé primaire composite (ListeQuestionnaireId).
J'ai un dao pour chacune des 3 entités. Aucun problème pour Membre et pour Questionnaire. Par contre les tests du dao de ListeQuestionnaire plantent :
enfin, les tests findAll et countAll plantent, les deux autres passent.
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 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("TestDao-context.xml") @DirtiesContext public class TestListeQuestionnaireDao { @Autowired private ListeQuestionnaireDao listeQuestionnaireDao; @Autowired private ServiceMembre serviceMembre; @Autowired private QuestionnaireDao questionnaireDao; private ListeQuestionnaire listeQuestionnaire1, listeQ2; private Membre benji, lola; @Before @Transactional public void startTransaction() throws ParseException{ benji = new Membre(); benji.setIdMembre("ben.joris"); benji = serviceMembre.saveOne(benji); Questionnaire q1 = new Questionnaire(); q1.setNumero("Q1"); q1.setTitre("Nutrition"); q1.setSexeDestinataire('b'); q1 = questionnaireDao.saveOne(q1); System.out.println("--------- TEST : enregistrement listeQuestionnaire1..."); listeQuestionnaire1 = new ListeQuestionnaire(); listeQuestionnaire1.setaRepondu(false); listeQuestionnaire1.setMembre(benji); listeQuestionnaire1.setQuestionnaire(q1); listeQuestionnaire1 = listeQuestionnaireDao.saveOne(listeQuestionnaire1); System.out.println("--------- TEST : fin startTransaction..."); } @Test @Transactional @Rollback public void testFindAll() { System.out.println("--------- TEST : testFindAll..."); List<ListeQuestionnaire> questionnaireAttendus = new ArrayList<ListeQuestionnaire>(); questionnaireAttendus.add(listeQuestionnaire1); List<ListeQuestionnaire> questionnairesObtenus = listeQuestionnaireDao.findAll(); Assert.assertEquals(questionnaireAttendus, questionnairesObtenus); } @Test @Transactional @Rollback public void testCountAll() { System.out.println("--------- TEST : testCountAll..."); Assert.assertEquals(1, listeQuestionnaireDao.countAll()); } @Test @Transactional @Rollback public void testLoad() { ListeQuestionnaire questionnaire = listeQuestionnaireDao.getOne(listeQuestionnaire1.getId()); Assert.assertEquals(listeQuestionnaire1, questionnaire); } @Test @Transactional @Rollback public void testDelete() { listeQuestionnaireDao.deleteOne(listeQuestionnaire1); listeQuestionnaire1 = listeQuestionnaireDao.getOne(listeQuestionnaire1.getId()); Assert.assertNull(listeQuestionnaire1); }
pour les deux qui plantent, j'obtiens l'erreur :
sachant qu'en console j'ai les traces suivantes avant l'erreur :
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 javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1235) at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1168) at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:250) at fr.statlife.protoE4N.data.dao.jpa.ListeQuestionnaireDaoImpl.findAll(ListeQuestionnaireDaoImpl.java:32) at fr.statlife.protoE4N.data.dao.jpa.TestListeQuestionnaireDao.testFindAll(TestListeQuestionnaireDao.java:88) 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.InvokeMethod.evaluate(InvokeMethod.java:20) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28) 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) Caused by: org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:96) at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66) at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275) at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:262) at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:178) at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321) at org.hibernate.event.def.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:64) at org.hibernate.impl.SessionImpl.autoFlushIfRequired(SessionImpl.java:1175) at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1251) at org.hibernate.impl.QueryImpl.list(QueryImpl.java:102) at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:241) ... 31 more Caused by: java.sql.BatchUpdateException: Cannot add or update a child row: a foreign key constraint fails (`protoe4n`.`listequestionnaire`, CONSTRAINT `FK8C6EC97C87F51B2E` FOREIGN KEY (`idMembre`) REFERENCES `Membre` (`idMembre`)) at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:2024) at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:1449) at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70) at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268) ... 39 more Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Cannot add or update a child row: a foreign key constraint fails (`protoe4n`.`listequestionnaire`, CONSTRAINT `FK8C6EC97C87F51B2E` FOREIGN KEY (`idMembre`) REFERENCES `Membre` (`idMembre`)) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) at java.lang.reflect.Constructor.newInstance(Constructor.java:513) at com.mysql.jdbc.Util.handleNewInstance(Util.java:411) at com.mysql.jdbc.Util.getInstance(Util.java:386) at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1039) at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3597) at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3529) at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1990) at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2151) at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2625) at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2119) at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2415) at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:1976) ... 42 more
Ce que ça me dis, c'est que l'enregistrement de ListeQuestionnaire n'est pas
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 Hibernate: select membre0_.idMembre as idMembre1_1_, membre0_.codeIdentification as codeIden2_1_1_, membre0_.dateNaissance as dateNais3_1_1_, membre0_.infosPerso_idInfosPerso as infosPerso6_1_1_, membre0_.password as password1_1_, membre0_.sexe as sexe1_1_, infosperso1_.idInfosPerso as idInfosP1_2_0_, infosperso1_.codePostal as codePostal2_0_, infosperso1_.email as email2_0_, infosperso1_.poids as poids2_0_, infosperso1_.taille as taille2_0_, infosperso1_.ville as ville2_0_ from Membre membre0_ left outer join InfosPerso infosperso1_ on membre0_.infosPerso_idInfosPerso=infosperso1_.idInfosPerso where membre0_.idMembre=? Hibernate: insert into Questionnaire (numero, sexeDestinataire, titre) values (?, ?, ?) --------- TEST : enregistrement listeQuestionnaire1... Hibernate: select listequest0_.idMembre as idMembre4_0_, listequest0_.idQuestionnaire as idQuesti2_4_0_, listequest0_.aRepondu as aRepondu4_0_ from ListeQuestionnaire listequest0_ where listequest0_.idMembre=? and listequest0_.idQuestionnaire=? --------- TEST : fin startTransaction... --------- TEST : testFindAll... Hibernate: insert into ListeQuestionnaire (aRepondu, idMembre, idQuestionnaire) values (?, ?, ?) WARN - JDBCExceptionReporter - SQL Error: 1452, SQLState: 23000 ERROR - JDBCExceptionReporter - Cannot add or update a child row: a foreign key constraint fails (`protoe4n`.`listequestionnaire`, CONSTRAINT `FK8C6EC97C87F51B2E` FOREIGN KEY (`idMembre`) REFERENCES `Membre` (`idMembre`)) ERROR - tractFlushingEventListener - Could not synchronize database state with session
fait tant qu'un autoFlush appelé par ma méthode findAll n'est pas appelé. Et aussi biensur qu'une contrainte de clé étrangère échoue.
Par contre, pour les deux tests qui plantent pas, il tente pas de faire d'insert de ListeQuestionnaire, y'a juste la requête select qui est appelée :
Donc le getOne et le deleteOne fonctionnent, mais j'ai pas l'impression qu'ils interagissent avec la base de données, mais plutôt que ça interagit juste avec le contexte de persistance... Enfin, je vois ça de mes yeux de débutante sur le sujet, donc je me trompe peut être
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 Hibernate: select membre0_.idMembre as idMembre1_1_, membre0_.codeIdentification as codeIden2_1_1_, membre0_.dateNaissance as dateNais3_1_1_, membre0_.infosPerso_idInfosPerso as infosPerso6_1_1_, membre0_.password as password1_1_, membre0_.sexe as sexe1_1_, infosperso1_.idInfosPerso as idInfosP1_2_0_, infosperso1_.codePostal as codePostal2_0_, infosperso1_.email as email2_0_, infosperso1_.poids as poids2_0_, infosperso1_.taille as taille2_0_, infosperso1_.ville as ville2_0_ from Membre membre0_ left outer join InfosPerso infosperso1_ on membre0_.infosPerso_idInfosPerso=infosperso1_.idInfosPerso where membre0_.idMembre=? Hibernate: insert into Questionnaire (numero, sexeDestinataire, titre) values (?, ?, ?) --------- TEST : enregistrement listeQuestionnaire1... Hibernate: select listequest0_.idMembre as idMembre4_0_, listequest0_.idQuestionnaire as idQuesti2_4_0_, listequest0_.aRepondu as aRepondu4_0_ from ListeQuestionnaire listequest0_ where listequest0_.idMembre=? and listequest0_.idQuestionnaire=? --------- TEST : fin startTransaction...
Je suis débutante avec spring JPA et hibernate, mais j'ai suivi pas mal de tutos sur le sujet. Cela dit, je manque quand même d'expérience sur le sujet et j'arrive pas à comprendre d'où vient le problème d'échec de la clé étrangère, ni pourquoi il sauvegarde pas mon Objet ListeQuestionnaire au moment où j'appelle la méthode saveOne du Dao...
voici le code du dao :
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) protected 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; } }un peu d'aide ou des conseils pour combler mes zones d'ombres seraient les bienvenus
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 = em.createQuery("select listeQ from ListeQuestionnaire listeQ ", ListeQuestionnaire.class); return query.getResultList(); } public int countAll() { TypedQuery<Long> query = em.createQuery("select count(listeQ) from ListeQuestionnaire listeQ", Long.class); return (query.getSingleResult()).intValue(); } }![]()
Partager