Bonjour,

Je lève une exception de type "a different object with the same identifier value was already associated with the session: [com.natixis.model.Enregistrement#2]" lorsque je veux mettre plusieurs fois le même objet dans une liste.

Contexte :

J'ai 3 classes principales :

Composant :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
public abstract class Composant {
 
	protected java.lang.Integer id;
	protected String nom;
	protected String description;
	protected String description_defaut;
	protected Set<Conteneur> conteneurs;
}
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
<hibernate-mapping>
	<class name="com.natixis.model.Composant" table="Composant"
		abstract="true">
		<id name="id" type="int">
			<column name="ID" />
			<generator class="increment" />
		</id>
		<property name="nom" type="java.lang.String">
			<column name="NOM" />
		</property>
		<property name="description" type="java.lang.String">
			<column name="DESCRIPTION" />
		</property>
		<property name="description_defaut" type="java.lang.String">
			<column name="DESCRIPTION_DEFAUT" />
		</property>
		<set name="conteneurs" table="ConteneurComposant" inverse="true">
			<key column="composantId" not-null="true" />
			<many-to-many column="conteneurId" class="com.natixis.model.Conteneur" />
		</set>
	</class>
</hibernate-mapping>
Conteneur :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
public abstract class Conteneur extends Composant {
 
	protected List<ConteneurComposant> listeComposants;
}
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
<hibernate-mapping>
	<joined-subclass name="com.natixis.model.Conteneur"
		extends="com.natixis.model.Composant" abstract="true">
		<key column="ID" />
		<list name="listeComposants" table="ConteneurComposant" lazy="false"
			cascade="all-delete-orphan">
			<key column="conteneurId" not-null="true" />
			<list-index column="ORDRE" />
			<one-to-many class="com.natixis.model.ConteneurComposant" />
		</list>
	</joined-subclass>
</hibernate-mapping>
ComposantConteneur :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
public class ConteneurComposant {
	private int id;
	private int multiplicite;
	private Composant composant;
}
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
<hibernate-mapping>
	<class name="com.natixis.model.ConteneurComposant" table="ConteneurComposant">
		<id name="id" type="int">
			<column name="ID" />
			<generator class="increment" />
		</id>
		<property name="multiplicite" type="integer">
			<column name="multiplicite" />
		</property>
		<many-to-one name="composant" class="com.natixis.model.Composant"
			lazy="false" cascade="all">
			<column name="composantId"></column>
		</many-to-one>
	</class>
</hibernate-mapping>
La classe Enregistrement est une classe fille de Conteneur (et donc de composant).

Objectif :

Mon objectif est de pouvoir ajouter plusieurs fois un composant identique avec une multiplicité différente dans un conteneur.
Pour cela, je passe par une classe intermédiaire (ConteneurComposant).

Cas Test :
  1. Création d'un conteneur1
  2. Création d'un composant1
  3. Ajout du composant1 au conteneur1 (via un ConteneurComposant)
  4. Sauvegarde du conteneur1 (et des autres Objets par cascade)
  5. Listing des composants existant
  6. Ajout du composant1 (via un nouveau ConteneurComposant)
  7. Sauvegarde du conteneur, ce qui provoque une remontée d'erreur


Pour sauvegarder le conteneur j'utilise la méthode suivante :
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
public class ConteneurDAO extends ComposantDAO {
 
	protected static void saveConteneur(Conteneur conteneur) {
		Global.logger.info("Sauvegarde du Conteneur " + conteneur.getNom());
		Session session = sessionFactory.openSession();
		Transaction tx = null;
		try {
			tx = session.beginTransaction();
			session.saveOrUpdate(conteneur);
			session.flush();
			tx.commit();
		} catch (HibernateException e) {
			if (tx != null) {
				tx.rollback();
			}
			throw e;
		} finally {
			session.close();
		}
	}
Pour lister les composants ciblés j'utilise la méthode suivante :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
	@SuppressWarnings("unchecked")
	public static List<Conteneur> listeConteneur() {
		Global.logger
				.debug("Récupère la liste des flux et des enregistrements.");
		List<Conteneur> list = null;
		Session session = sessionFactory.openSession();
		session.buildLockRequest(LockOptions.READ);
		list = (List<Conteneur>) session.createQuery("from Conteneur").list();
		session.close();
		Global.logger.debug("Récupération de " + list.size() + " Conteneur");
		return list;
	}
Je pense qu'il faut trouver un moyen pour utiliser la même instance des composants déjà chargés à chaque fois que je réalise une liste, mais j'ignore comment faire ?

Merci de l'aide que vous pourrez m'apporter