IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Spring Java Discussion :

HibernateTemplate et Illegal attempt to associate a collection with two open sessions [Data]


Sujet :

Spring Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 9
    Par défaut HibernateTemplate et Illegal attempt to associate a collection with two open sessions
    Bonjour,

    je travaille actuellement sur une application utilisant notamment Spring 2.5.6 et Hibernate 3.2.1.
    J'utilise un JDK 1.4.2 et ne peut en utiliser un autre à cause de contrainte de plateforme.

    En gros voilà la présentation du problème:
    - j'ai une couche service sur laquelle les transactions sont définies par un TransactionProxyFactoryBean.
    - j'ai une couche DAO qui effectue les accès aux données.
    Jusque là rien de transcendant...

    Au niveau modèle de données:
    - une table PointStock
    - une table Produit
    Un PointStock et liés à plusieurs produits.

    Concrètement en modèle objet: PointStock possède un attribut Map contenant des couples <String, Produit> (ce n'est pas forcément le plus logique mais je travail en particulier sur des exemples de code et non une application vouées à de la production)

    Voilà maintenant le code suivant:
    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
     
    public class DAOImplementation extends HibernateTemplate implements
    		DAOInterface {
     /*
    ...
     */
    	public PointStock insertProduitsForPointStock(Map produits, Long pointStockId){
    		PointStock pointStock = super.get(PointStock.class, pointStockId);
     
    		pointStock.getProduits().putAll(produits);
     
    		super.update(pointStock);
     
    		return pointStock;
    	}
    }
    La première interrogation à la BDD me ramène ce qu'il faut et lors du getProduit l'instance de PersistentMap est liés à une Session "n".
    Et lorsque l'appel à l'update est créé, il semblerait qu'il y ait utilisation d'une nouvelle session et donc je me retrouve avec :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions
    Au départ les deux appels (consultation/écriture) étaient séparés dans deux méthodes différentes appelées par mon Service. Ayant le problème cités, j'ai essayé de les ramener dans la même méthode DAO comme dans l'exemple ci-dessus mais même bloquage. Je ne vois pas du tout comment procédé pour garantir au sein d'une même transaction, l'utilisation d'une seule session.

    Informations supplémentaires:
    - hbm PointStock:
    Code xml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <hibernate-mapping package="test.metier">
      <class name="PointStock">
      <id name="idPointStock">
      	<generator class="native"/>
      </id>
      <property name="nom" />
      <map name="produits" cascade="all">
      	<key column="idPointStock"/>
      	<map-key type="string" column="keyProduit"/>
      	<one-to-many class="Produit"/>
      </map>
      </class>
    </hibernate-mapping>
    - OpenSessionInViewFilter dans le web.xml
    Code xml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    	<filter>
    		<filter-name>openSessionInViewFilter</filter-name>
    		<filter-class>
    			org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
    		</filter-class>
    		<init-param>
    			<param-name>singleSession</param-name>
    			<param-value>false</param-value>
    		</init-param>
    	</filter>
    	<filter-mapping>
    		<filter-name>openSessionInViewFilter</filter-name>
    		<url-pattern>/*</url-pattern>
    	</filter-mapping>

  2. #2
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 9
    Par défaut
    Bon j'ai effectué quelques modifications:
    1- configurer le filtre OpenSessionInViewFilter pour ne pas ouvrir plusieurs sessions:
    Code xml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <filter>
    	<filter-name>openSessionInViewFilter</filter-name>
    	<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
    	<init-param>
    		<param-name>singleSession</param-name>
    		<param-value>true</param-value>
    	</init-param>
    </filter>
    <filter-mapping>
    	<filter-name>openSessionInViewFilter</filter-name>
    	<url-pattern>/*</url-pattern>
    </filter-mapping>
    2- ne pas utiliser les méthodes CRUD du HibernateTemplate directement mais passer la session courante:
    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
     
    public class DAOImplementation extends HibernateTemplate implements
    		DAOInterface {
     /*
    ...
     */
    	public void updatePointStock(PointStock pointStock) {
    		//super.update(pointStock);
    		getSessionFactory().getCurrentSession().update(pointStock);
    	}
     
    	public PointStock insertProduitsForPointStock(Map produits, Long pointStockId){
    		Session session = getSessionFactory().getCurrentSession();
     
    		PointStock pointStock = (PointStock) session.get(PointStock.class, pointStockId); 
     
    		pointStock.getProduits().putAll(produits);
     
    		session.update(pointStock);
     
    		return pointStock;
    	}
    }
    En effet j'ai constaté que les méthodes du HibernateTemplate créaient une nouvelle session pour chaque opération (????)

    Et joie, je n'ai plus mon erreur !

    Sauf que maintenant il semblerait que mon gestionnaire de transactions laisse ma session en FlushMode.NEVER donc sur un simple update, il n'y a plus d'écriture... Pourtant je pense avoir défini mon gestionnaire de Transaction comme il faut. Le code ci-dessous montre que la transaction est placée sur le bean businessDelegate, les méthodes de celui-ci faisant appel à la DAO ci-dessus par la suite. (la configuration se veut simpliste et permissive afin de valider au moins une fois un test d'écriture)
    Code xml : 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
     
    <bean id="myTransactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    	<property name="sessionFactory">
    		<ref local="sessionFactory" />
    	</property>
    </bean>
     
    <!-- proxy vers le Business Delegate avec support des transactions --> 
    <bean id="transactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">	
    	<property name="transactionManager"><ref local="myTransactionManager"/></property>
    	<property name="target"><ref local="businessDelegate"/></property>
    	<property name="transactionAttributes">
    		<props>
    			<prop key="*">PROPAGATION_REQUIRED</prop>
    		</props>
    	</property>
    </bean>

    Je n'ai donc plus d'erreur, mais plus d'écritures non plus... je tourne un peu rond... une idée?
    Merci d'avance

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2007
    Messages
    9
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2007
    Messages : 9
    Par défaut
    Bon problème résolu...
    la solution est cette fois très bête:
    j'avais oublié de faire pointer l'objet appelant le service sur le bean du proxy... il pointait encore directement sur le service...

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 2
    Dernier message: 26/02/2009, 09h07
  2. Réponses: 6
    Dernier message: 20/07/2007, 14h17
  3. Réponses: 3
    Dernier message: 28/02/2007, 16h21
  4. Réponses: 2
    Dernier message: 13/10/2006, 17h38
  5. Réponses: 4
    Dernier message: 20/07/2006, 17h26

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo