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 :

Challenge ! Spring + Hibernate = double transaction ?


Sujet :

Spring Java

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2007
    Messages : 5
    Points : 3
    Points
    3
    Par défaut Challenge ! Spring + Hibernate = double transaction ?
    Salut @ tous !

    Je suis confronté à un pb avec Hibernate, Spring et les transactions : "[save|createQuery] is not valid without active transaction". J'utilise une Datasource configurée avec Tomcat, et je veux utiliser AOP pour la gestion des transactions :
    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
     
    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
     <property name="mappingResources">
      <list>
       <!--[all my mappings]-->
      </list>
     </property>
     <property name="hibernateProperties">
      <value>
       hibernate.connection.datasource=java:comp/env/jdbc/myapp
       hibernate.dialect=org.hibernate.dialect.Oracle9Dialect
       hibernate.current_session_context_class=thread
       hibernate.transaction.factory_class=org.springframework.orm.hibernate3.SpringTransactionFactory
       hibernate.show_sql=true
      </value>
     </property>
    </bean>
     
    <bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
     <property name="sessionFactory" ref="sessionFactory" />
    </bean>
     
    <tx:advice id="txAdvice" transaction-manager="txManager">
     <tx:attributes>
      <tx:method name="get*" read-only="true" />
      <tx:method name="*" isolation="READ_COMMITTED" rollback-for="com.myapp.framework.exception.ManagerException" />
     </tx:attributes>
    </tx:advice>
     
    <aop:config>
     <aop :p ointcut id="pcManager1" expression="execution(public * com.myapp.framework.dao.manager..*(..))" />
     <aop :p ointcut id="pcManager2" expression="execution(public * com.myapp.dao.manager..*(..))"/>
     <aop:advisor advice-ref="txAdvice" pointcut-ref="pcManager1" />
     <aop:advisor advice-ref="txAdvice" pointcut-ref="pcManager2" />
    </aop:config>
    Tout semble OK dans les logs :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    opened session at timestamp: 12306501743
    DEBUG [org.hibernate.jdbc.ConnectionManager] (ConnectionManager.java:415) - opening JDBC connection
    DEBUG [org.hibernate.transaction.JDBCTransaction] (JDBCTransaction.java:54) - begin
    DEBUG [org.hibernate.transaction.JDBCTransaction] (JDBCTransaction.java:59) - current autocommit status: true
    DEBUG [org.hibernate.transaction.JDBCTransaction] (JDBCTransaction.java:62) - disabling autocommit
    DEBUG [org.hibernate.impl.SessionImpl] (SessionImpl.java:220) - opened session at timestamp: 12306501743
    et lorsque j'appelle une sauvegarde sur la session, j'ai une exception :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    session = ((SessionFactory) MyBeanFactoryFromSpring.getInstance().getBean(BeanConstants.SESSION_FACTORY)).getCurrentSession();
    session.save(myObject);
    .. ce qui provoque ..
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    org.hibernate.HibernateException: save is not valid without active transaction
     at org.hibernate.context.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:297)
    ...
    De plus, la transaction ouverte précédemment semble pourtant bien faire un rollback !!
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    DEBUG [org.hibernate.transaction.JDBCTransaction] (JDBCTransaction.java:152) - rollback
    DEBUG [org.hibernate.transaction.JDBCTransaction] (JDBCTransaction.java:193) - re-enabling autocommit
    DEBUG [org.hibernate.transaction.JDBCTransaction] (JDBCTransaction.java:163) - rolled back JDBC Connection
    DEBUG [org.hibernate.jdbc.ConnectionManager] (ConnectionManager.java:296) - transaction completed on session with on_close connection release mode; be sure to close the session to release JDBC resources!
    DEBUG [org.hibernate.jdbc.ConnectionManager] (ConnectionManager.java:435) - releasing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)]
    Enfin, à noter que lorsque j'utilise la méthode "manuelle" (à savoir beginTransaction et commit), cela fonctionne !!! Je n'y comprends plus rien..

    Quelqu'un a une idée sur cette "double transaction" ?

  2. #2
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2009
    Messages
    92
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2009
    Messages : 92
    Points : 108
    Points
    108
    Par défaut
    Il semble que la transaction ne soit pas ouverte quand tu invoques le code suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    session = ((SessionFactory) MyBeanFactoryFromSpring.getInstance().getBean(BeanConstants.SESSION_FACTORY)).getCurrentSession();
    session.save(myObject);
    Est-ce que ce code est bien appelé dans une des méthodes correspondant à tes pointcuts ?

  3. #3
    Nouveau Candidat au Club
    Inscrit en
    Octobre 2009
    Messages
    1
    Détails du profil
    Informations forums :
    Inscription : Octobre 2009
    Messages : 1
    Points : 1
    Points
    1
    Par défaut re: Challenge ! Spring + Hibernate = double transaction ?
    Techniques alternatives
    Dans certains projets, les techniques traditionnelles ne peuvent pas être implémentées facilement à cause d'un historique sans Spring et d'erreurs de programmation antérieures.

    [modifier]Configuration hibernate.cfg.xml
    Dans l'exemple de configuration précédente, le bean de SessionFactory remplace totalement le fichier de configuration hibernate.cfg.xml. Dans le cadre d'une intégration progressive de Spring, il peut être intéressant de brancher le SessionFactory sur un fichier hibernate.cfg.xml existant :

    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="configLocation"> <value>hibernate.cfg.xml</value> </property> </bean>

    Le problème de cette technique est que la gestion automatique des transactions par Spring ne fonctionne plus. Un contournement est de modifier le fichier de configuration d'Hibernate :

    <hibernate-configuration>
    <session-factory>
    ...
    <property name="hibernate.current_session_context_class">
    org.springframework.orm.hibernate3.SpringSessionContext
    </property>
    ...
    </session-factory>
    </hibernate-configuration>
    Un nouveau problème apparaît alors : Les sessions et transactions ne fonctionnent plus hors de Spring ! Ce qui est très gênant pour une intégration progressive.

    Pour contourner ce nouveau problème, il faut initialiser la synchronisation entre Spring et les threads :

    if (! TransactionSynchronizationManager.isSynchronizationActive())
    TransactionSynchronizationManager.initSynchronization();
    L'initialisation doit être faite une seule fois par thread, sous peine d'une exception de type java.lang.IllegalStateException, avec le message "Cannot activate transaction synchronization - already active". C'est pour éviter celà que je fais un test préalable.

    Grâce à cette technique, les mêmes classes de DAO peuvent être utilisées par des services dans Spring, utilisant donc le TransactionManager de Spring, et par des services externes à Spring, manipulant directement des sessions et transactions via les classes d'Hibernate.

    Attention : cette technique n'est généralement pas préconisée ; elle est utile dans une période de transition.

    Récupérée de « http://www.jtips.info/index.php?titl...g-Transactions »

    PS: j'ai trouvé ça sur http://www.jtips.info/index.php?titl...g-Transactions

Discussions similaires

  1. [Data] Spring - Hibernate => Transactions
    Par Flam dans le forum Spring
    Réponses: 3
    Dernier message: 05/06/2012, 17h24
  2. Spring + Hibernate + JBoss : Transaction AOP
    Par meryodev dans le forum Wildfly/JBoss
    Réponses: 0
    Dernier message: 03/06/2011, 23h02
  3. [Data] Problème gestion transactions spring/hibernate
    Par Reno17 dans le forum Spring
    Réponses: 4
    Dernier message: 04/02/2010, 15h36
  4. [Data] Problème de transaction Spring Hibernate
    Par totoz dans le forum Spring
    Réponses: 0
    Dernier message: 01/07/2009, 16h21
  5. [Spring][Hibernate] Transaction déclarative
    Par mauvais_karma dans le forum Hibernate
    Réponses: 13
    Dernier message: 03/07/2008, 17h09

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