Bonjour, je me retrouve avec cette erreur dans mon projet java lorsque je veux supprimer un objet "Gisement". J'ai essayé de trouver d'où cela pouvait venir en cherchant sur internet mais sans succès.
Cela pourrait venir d'un tableau mal déclaré, d'une mauvaise gestion des CASCADE ou encore des transactions.
Je vais reprendre ce qui est, pour moi, important à montrer pour m'aider à résoudre ce problème.
J'avais déjà eu ce souci dans un projet que j'avais abandonné en cours de route. Je pense que cela doit venir de la même chose.
Hibernate valide sans problème ma base de données, le problème ne vient pas de là mais sans doute d'une ignorance de ma part dans mon code.
Je suis le même fonctionnement pour un autre (aussi une suprresion) cas et je n'ai pas cette erreur.
L'erreur se déclenche sur le "session.delete(obj)" de abstractDao et si on remonte, il englobe ce code :
Dans un première temps, le message d'erreur complet :
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 public abstract class AbstractDao<T> { //protected static final Logger LOGGER = LogManager.getLogger(AbstractDao.class); protected Class<T> modelClass; private SessionFactory sf; private InitSessionFactory i = new InitSessionFactory(); public void setmodelClass(Class<T> modelClass) { this.modelClass = modelClass; sf = i.getSessionFactory(); } protected final Session getSession() { Session session = null; try { session = this.sf.getCurrentSession(); } catch (Exception e) { //LOGGER.error(e); } if (session == null) session = sf.openSession(); return session; } //session.delete(obj);
Maintenant, pour mes différentes classes, j'ai d'un côté le couple "Gisement" qui est la classe parente de "Mineraux" et "Gaz".
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 Type Rapport d'exception message org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions. Collection : [Models.Gisement.listeEquipesGisement#5] description Le serveur a rencontré une erreur interne qui l'a empêché de satisfaire la requête. exception javax.persistence.PersistenceException: org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions. Collection : [Models.Gisement.listeEquipesGisement#5] org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:154) org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:181) org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:188) org.hibernate.internal.SessionImpl.fireDelete(SessionImpl.java:914) org.hibernate.internal.SessionImpl.delete(SessionImpl.java:836) Dao.AbstractDao.delete(AbstractDao.java:70) Controllers.AdminPersistServlet.doGet(AdminPersistServlet.java:239) javax.servlet.http.HttpServlet.service(HttpServlet.java:655) javax.servlet.http.HttpServlet.service(HttpServlet.java:764) org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) cause mère org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions. Collection : [Models.Gisement.listeEquipesGisement#5] org.hibernate.collection.internal.AbstractPersistentCollection.setCurrentSession(AbstractPersistentCollection.java:693) org.hibernate.event.internal.OnUpdateVisitor.processCollection(OnUpdateVisitor.java:46) org.hibernate.event.internal.AbstractVisitor.processValue(AbstractVisitor.java:104) org.hibernate.event.internal.AbstractVisitor.processValue(AbstractVisitor.java:65) org.hibernate.event.internal.AbstractVisitor.processEntityPropertyValues(AbstractVisitor.java:59) org.hibernate.event.internal.AbstractVisitor.process(AbstractVisitor.java:126) org.hibernate.event.internal.DefaultDeleteEventListener.onDelete(DefaultDeleteEventListener.java:119) org.hibernate.event.internal.DefaultDeleteEventListener.onDelete(DefaultDeleteEventListener.java:72) org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:93) org.hibernate.internal.SessionImpl.fireDelete(SessionImpl.java:904) org.hibernate.internal.SessionImpl.delete(SessionImpl.java:836) Dao.AbstractDao.delete(AbstractDao.java:70) Controllers.AdminPersistServlet.doGet(AdminPersistServlet.java:239) javax.servlet.http.HttpServlet.service(HttpServlet.java:655) javax.servlet.http.HttpServlet.service(HttpServlet.java:764) org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) note La trace complète de la cause mère de cette erreur est disponible dans les fichiers journaux de ce serveur.
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 @Entity @Inheritance(strategy = InheritanceType.JOINED) @DiscriminatorColumn(name = "type_gisement", discriminatorType = DiscriminatorType.STRING) @Table(name="Gisement") public class Gisement { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; /* https://stackoverflow.com/questions/32749531/psqlexception-the-column-index-is-out-of-range-7-number-of-columns-6-postg */ // add @Column(insertable = false, updatable = false) annotation to the discriminator field @Column(name="type_gisement", nullable = false, insertable = false, updatable = false) protected String typeGisement; //@OneToMany(targetEntity=Equipe.class, mappedBy = "gisement", fetch = FetchType.LAZY) @OneToMany(mappedBy = "gisement") protected List<Equipe> listeEquipesGisement; @Column(name="date_mise_service") private LocalDate dateMiseEnService; @Column(name="rendement_mensuel") private int rendementMensuel; public Gisement() { // } public Gisement(LocalDate dateMiseEnService, int rendementMensuel) { this(); this.dateMiseEnService = dateMiseEnService; this.rendementMensuel = rendementMensuel; this.listeEquipesGisement = new ArrayList<>(); } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getTypeGisement() { return typeGisement; } public void setTypeGisement(String typeGisement) { this.typeGisement = typeGisement; } public List<Equipe> getListeEquipesGisement() { return listeEquipesGisement; } public void setListeEquipesGisement(List<Equipe> listeEquipesGisement) { this.listeEquipesGisement = listeEquipesGisement; } public LocalDate getDateMiseEnService() { return dateMiseEnService; } public void setDateMiseEnService(LocalDate dateMiseEnService) { this.dateMiseEnService = dateMiseEnService; } public int getRendementMensuel() { return rendementMensuel; } public void setRendementMensuel(int rendementMensuel) { this.rendementMensuel = rendementMensuel; } }
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 import org.hibernate.annotations.OnDelete; import org.hibernate.annotations.OnDeleteAction; import javax.persistence.*; import java.time.LocalDate; @Entity @PrimaryKeyJoinColumn(name="id", foreignKey=@ForeignKey(name = "FK_Gaz_Guisement")) @DiscriminatorValue("gaz") @Table(name="Gaz") @OnDelete(action = OnDeleteAction.CASCADE) public class Gaz extends Gisement { private double densite; @Column(name="type_gaz") private String typeGaz; public Gaz() { // } public Gaz(LocalDate dateMiseEnService, int rendementMensuel, double densite, String typeGaz) { super(dateMiseEnService, rendementMensuel); this.densite = densite; this.typeGaz = typeGaz; } public double getDensite() { return densite; } public void setDensite(double densite) { this.densite = densite; } public String getTypeGaz() { return typeGaz; } public void setTypeGaz(String typeGaz) { this.typeGaz = typeGaz; }Ma classe "Equipe" qui a une relation ManyToOne bidirectionnelle avec Gisement. C'est à dire qu'une equipe ne travail que sur un gisement à la fois alors qu'un gisement peut avoir plusieurs équipes
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 @PrimaryKeyJoinColumn(name="id", foreignKey=@ForeignKey(name = "FK_Mineraux_Guisement")) @DiscriminatorValue("mineraux") @Table(name="Mineraux") @OnDelete(action = OnDeleteAction.CASCADE) public class Mineraux extends Gisement { private double purete; @Column(name="type_mineraux") private String typeMineraux; public Mineraux(){ // } public Mineraux(LocalDate dateMiseEnService, int rendementMensuel, double purete, String typeMineraux) { super(dateMiseEnService, rendementMensuel); this.purete = purete; this.typeMineraux = typeMineraux; } public double getPurete() { return purete; } public void setPurete(double purete) { this.purete = purete; } public String getTypeMineraux() { return typeMineraux; } public void setTypeMineraux(String typeMineraux) { this.typeMineraux = typeMineraux; } }
Ma classe "AbstractDao" :
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 import javax.persistence.*; import java.io.Serializable; @Entity public class Equipe implements Serializable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; @ManyToOne // nom de la colonne qui sera une clef étrangère de Gisement DANS Equipe //@JoinColumn(name="id_gisement", nullable = false) @JoinColumn(name="id_gisement") private Gisement gisement; private String nom; public Equipe(){ // } public Equipe(String nom, Gisement gisement) { this.nom = nom; this.gisement = gisement; } public int getId() { return id; } public void setId(int id) { this.id = id; } public Gisement getGisement() { return gisement; } public void setGisement(Gisement gisement) { this.gisement = gisement; } public String getNom() { return nom; } public void setNom(String nom) { this.nom = nom; } }
Ainsi que la classe "InitSessionFactory :
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107 public abstract class AbstractDao<T> { //protected static final Logger LOGGER = LogManager.getLogger(AbstractDao.class); protected Class<T> modelClass; private SessionFactory sf; private InitSessionFactory i = new InitSessionFactory(); public void setmodelClass(Class<T> modelClass) { this.modelClass = modelClass; sf = i.getSessionFactory(); } protected final Session getSession() { Session session = null; try { session = this.sf.getCurrentSession(); } catch (Exception e) { //LOGGER.error(e); } if (session == null) session = sf.openSession(); return session; } protected final Transaction getTransaction(Session session) { Transaction tx = session.getTransaction(); if (!TransactionStatus.ACTIVE.equals(tx.getStatus())) tx = session.beginTransaction(); return tx; } public final void create(T obj) { Session session = this.getSession(); Transaction tx = null; try { tx = this.getTransaction(session); session.save(obj); tx.commit(); } catch (RuntimeException e) { if (tx != null) tx.rollback(); throw e; // Gérer le message (log, affichage, etc.) } finally { //session.close(); session.close(); } // return id; } public final void delete(T obj) { Session session = this.getSession(); Transaction tx = null; try { tx = this.getTransaction(session); session.delete(obj); tx.commit(); } catch (RuntimeException e) { if (tx != null) tx.rollback(); throw e; // Gérer le message (log, affichage, etc.) } finally { session.close(); } } public final void update(T obj) { Session session = null; Transaction tx = null; try { session = this.getSession(); tx = this.getTransaction(session); session.saveOrUpdate(obj); tx.commit(); } catch (RuntimeException e) { if (tx != null) tx.rollback(); throw e; // Gérer le message (log, affichage, etc.) } finally { session.close(); } } public T getById(int id) { return getSession().get(modelClass, id); } public T getById(String id) { return getSession().get(modelClass, id); } @SuppressWarnings("unchecked") public List<T> getAll() { return getSession().createQuery("from " + modelClass.getName()).list(); } public abstract List<T> search(T criteria); }
GisementDAO qui l'implémente :
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 import org.hibernate.SessionFactory; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.cfg.Configuration; import org.hibernate.service.ServiceRegistry; public class InitSessionFactory { private SessionFactory sessionFactory; public InitSessionFactory() { //configuration.configure("classpath:com/resources/hibernate.cfg.xml"); Configuration configuration = new Configuration().configure("/hibernate.cfg.xml"); //Différentes classes //configuration.addAnnotatedClass(.class); configuration.addAnnotatedClass(Equipe.class); configuration.addAnnotatedClass(Gisement.class); configuration.addAnnotatedClass(Mineraux.class); configuration.addAnnotatedClass(Gaz.class); ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build(); sessionFactory = configuration.buildSessionFactory(serviceRegistry); } protected SessionFactory getSessionFactory() { return sessionFactory; } }
La partie de mon code qui fait appel à la fonction "delete" de mon DAO lorsque je veux supprimer un gisement (il fait suite à un formulaire) :
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 import Models.Gisement; import java.util.List; public class GisementDao extends AbstractDao<Gisement> { public GisementDao() { this.setmodelClass(Gisement.class); } //pas complet @Override public List<Gisement> search(Gisement criteria) { return null; } }
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14 if(formType.equals("supprimerGisement")) { Integer idGisement = Integer.parseInt(request.getParameter("gisementEnCours")); String typeGisement = gisementDao.getById(idGisement).getTypeGisement(); if(typeGisement.equals("mineraux")) { Mineraux mineraux = minerauxDao.getById(idGisement); minerauxDao.delete(mineraux); }else if(typeGisement.equals("gaz")) { Gaz gaz = gazDao.getById(idGisement); gazDao.delete(gaz); } }
Partager