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

Hibernate Java Discussion :

[Spring][Hibernate] Transaction déclarative


Sujet :

Hibernate Java

  1. #1
    Membre habitué
    Inscrit en
    Décembre 2002
    Messages
    186
    Détails du profil
    Informations forums :
    Inscription : Décembre 2002
    Messages : 186
    Points : 130
    Points
    130
    Par défaut [Spring][Hibernate] Transaction déclarative
    salut
    j'utilise spring 1.2 et hibernate3

    j'ai des dao pour les opertion CRUD
    et des services pour la partie métier

    la dao est gérée par spring et les transactions sont programmatique (pour l'instant) du style sessio.beginTransaction, sessio.rollback()...
    ca marche bien

    ensuite mes services utilise des dao: par exemple pour creer un compte client, il faut d'abord faire compteDAO.create() puis clientDAO.create() à la suite.
    Le pb c que si ya une erreur dans le dernier create, il ya bien un rollback au niveau de la dao, mais pas pour toute les opérations du sevice (dans le cas présent, on peut avoir un compte de crer et pas le client)

    Donc pour les services j'utilise les transaction déclaratives grace a spring AOP et le transactionManager de Hibernate: voici le bean.xml:


    <beans>

    <!-- ############# Source de donnée ############# -->
    <bean id="myDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName" value="java:comp/env/jdbc/siteCom"/>
    </bean>


    <!-- ############# Hibernate SessionFactory ############# -->
    <bean id="hibSessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean" >
    <property name="dataSource">
    <ref local="myDataSource"/>
    </property>
    <property name="configLocation">
    <value>WEB-INF/hibernate.cfg.xml</value>
    </property>
    </bean>



    <!-- ############# Transaction Management for DAO ############# -->
    <bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory">
    <ref local="hibSessionFactory"/>
    </property>
    </bean>


    <bean id="userBL" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    <property name="transactionManager" ref="txManager"/>
    <property name="target" ref="userBLTarget"/>
    <property name="transactionAttributes">
    <props>
    <prop key="créerCompteClient*">PROPAGATION_REQUIRED</prop>
    </props>
    </property>
    </bean>



    <!-- ############# DAO ############# -->
    <bean id="clientManager" class="domain.hibernate.ClientDAOHib">
    <property name="sessionFactory">
    <ref local="hibSessionFactory"/>
    </property>
    </bean>
    <bean id="produitManager" class="domain.hibernate.ProduitDAOHib">
    <property name="sessionFactory">
    <ref local="hibSessionFactory"/>
    </property>
    </bean>
    <bean id="commandeManager" class="domain.hibernate.CommandeDAOHib">
    <property name="sessionFactory">
    <ref local="hibSessionFactory"/>
    </property>
    </bean>
    <bean id="compteManager" class="domain.hibernate.CompteDAOHib">
    <property name="sessionFactory">
    <ref local="hibSessionFactory"/>
    </property>
    </bean>




    <!-- ############# Logique Métier ############# -->
    <bean id="userBLTarget" class="logic.UserBLImpl">
    <property name="clientManager" ref="clientManager" />
    <property name="compteManager" ref="compteManager" />
    </bean>


    </beans>

    ... et voici le code du service:

    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
     
    public Client créerCompteClient(String nom, String prenom, 
                                        String rue, String ville, String codePostal,
                                        String numTel, String mail,
                                        String login, String pass ){
     
     
            Compte cpt = null;
            Client client = null;
            try{
                cpt = new Compte(login, pass, mail, new Role(Role.CLIENT)); // TODO passer en Role.nouvel-inscrit puis activer... & Role.CLIENT
                System.out.println("Création d'un Compte...!");
                // PB TRANSACTIONS: si la création du client échoue, le compte n'est pas supprimé?
                cpt = compteManager.createCompte(cpt);
     
                client = new Client(nom, prenom, numTel, rue, ville, codePostal, cpt);
                client = clientManager.createClient(client);
     
            }
            catch(Exception e){
                System.out.println("Erreru UserBL dans  Création compte client a echoué\n" + e.getMessage());
            }
     
     
     
            return client;
        }

    Pourtant ca ne marche pas, je ne sais pas comment faire un rollback:
    est ce qu'il faut lever une exception specifique? ne pas capturer d'exception?? est ce que PROPAGATION_REQUIRED est approprié? je ne comprend pas la signification des autres type de transaction!

    g besoin d'un coup de main! mercvi d'avance

  2. #2
    Membre averti
    Inscrit en
    Août 2005
    Messages
    352
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 352
    Points : 427
    Points
    427
    Par défaut
    Le rollback aura lieu si ton proxy transactionnel détecte que ta méthode renvoie une exception unchecked (comportement par défaut qui peut être modifié en précisant des règles pour le rollback).
    Si aucune exception unchecked est levée, le comportement par défaut sera de commiter la transaction.
    Dans ton exemple, la méthode intercepte les exceptions levées par ton DAO, les loggue avec un message d'erreur et ne fait rien d'autre. J'imagine que tu faisais ton rollback programmatiquement à ce niveau.
    Plusieurs solutions sont envisageables :
    - propager l'exception, soit dans une exception unchecked (rollback par défaut), soit dans une exception checked (comportement à modifier, cf. la doc de spring),
    - supprimer le bloc try-catch pour laisser se propager la DataAccessException.

  3. #3
    Membre habitué
    Inscrit en
    Décembre 2002
    Messages
    186
    Détails du profil
    Informations forums :
    Inscription : Décembre 2002
    Messages : 186
    Points : 130
    Points
    130
    Par défaut
    salut et merci beaucoup pour les eclaircissements
    par contre je ne suis pas certain de comprendre la différence entre checked (exception perso???) & uncheked (encapsulée/dérivée d'une DataAccessException???)

    g donc décidé de tester les unchecked exception:
    dans le corps de la fonctiuon je leve une exception spring dérivée d'une DataAccessException et la CA MARCHE!
    Ensuite pour la logique applicative qui ne veut pas lever ce type d'exception (car il n'y a pas forcement de pb de dao) g dis a Spring les Exception qui doivent conduir a un rollback (PROPAGATION REQUIRED, -excpetion)
    et la encore ca marche!

    Par contre, est ce que je pourai avoir plus de précision sur ce que signifie:
    Transactions read/write
    Isolation Level: TransactionDefinition.ISOLATION_DEFAULT
    Timeout: TransactionDefinition.TIMEOUT_DEFAULT

    merci

  4. #4
    Membre averti
    Inscrit en
    Août 2005
    Messages
    352
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 352
    Points : 427
    Points
    427
    Par défaut
    Les checked exceptions héritent de java.lang.Exception.
    Les unchecked (ou runtime) exceptions héritent de java.lang.RuntimeException.
    DataAccessException hérite de RuntimeException et constitue la racine d'une hiérarchie d'exceptions liées à l'accès aux données.
    Les exceptions JDBC (ou hibernate dans ton cas) sont traduites en sous-classes de DataAccesException par JDBCTemplate (ou HibernateTemplate).

    Concernant tes tests :
    - premier essai : DataAccessException étant une RuntimeException, c'est normal que le rollback se fasse,
    - deuxième essai : le fait de rajouter '-Exception' va faire que la transaction sera rollbackée quelque soit le type d'exception retourné par la méthode.

    Concernant tes questions sur les attributs :
    - transaction read-Only : flag pour indiquer que la transaction ne va pas modifier d'état persistant (hibernate ne détectera pas les modifications sur les objets et ne va pas faire de flush)
    - timeout : c'est le délai pendant lequel la transaction est valide. Passé ce délai, on fait un rollback de la transaction
    - isolation level : définit le niveau d'isolation de la transaction (cf le I dans ACID), si tu ne vois pas à quoi ca correspond trouve toi un site sur le sujet ou un bon bouquin ("hibernate in action" ou un livre sur spring par exemple), c'est vraiment un sujet important à connaitre.

  5. #5
    Membre habitué
    Inscrit en
    Décembre 2002
    Messages
    186
    Détails du profil
    Informations forums :
    Inscription : Décembre 2002
    Messages : 186
    Points : 130
    Points
    130
    Par défaut
    bon alors ca marchait tres bien mais depuis que je suis passé de spring1.2.2 à 1.2.4 et hibernate3.0 à 3.1beta2

    je précise que j'utilise pas JCA mais les transaction d'Hibernate

    maintenant g l'erreur transaction already started.
    euh oui c normal, ou est le pb?

    *Voila comment ca se passe:
    busineeMethode(){ // transaction t1déclarative débute
    dao.methode1() // transaction t2 programmatique débute puis termine
    dao.methode2() // transaction t3 programmatique débute puis termine
    } // transaction t1 déclarative se termine
    ca plante à l'appel de la méthode 1 (t1 commence, puis t2...)

    Si vous avez ce probleme ou une petite idée, je vais regarder si ca vient bien du changement de jar

  6. #6
    Membre averti
    Inscrit en
    Août 2005
    Messages
    352
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 352
    Points : 427
    Points
    427
    Par défaut
    Avant toute chose, pourquoi mélanges tu gestion programmatique et déclarative des transactions ?
    Le DAO ne devrait pas contenir de code relatif à l'ouverture/fermeture de transaction. Si tu veux gérer programmatiquement tes transactions, je te conseille de le faire au niveau du service. La gestion des transactions a plus sa place à ce niveau et c'est pour cela que Spring préconise une démarcation des transactions au niveau des interfaces métier.
    Exemple pour que tu comprennes : imagine que tu aies besoin de methode1() ou methode2() dans un contexte différent où ces 2 méthodes doivent utiliser la transaction en cours.

    maintenant g l'erreur transaction already started.
    euh oui c normal, ou est le pb?

    *Voila comment ca se passe:
    busineeMethode(){ // transaction t1déclarative débute
    dao.methode1() // transaction t2 programmatique débute puis termine
    dao.methode2() // transaction t3 programmatique débute puis termine
    } // transaction t1 déclarative se termine
    Il semblerait que t1 et t2 correspondent à la même transaction et que tu cherches à commencer une transaction déjà ouverte.

  7. #7
    Membre habitué
    Inscrit en
    Décembre 2002
    Messages
    186
    Détails du profil
    Informations forums :
    Inscription : Décembre 2002
    Messages : 186
    Points : 130
    Points
    130
    Par défaut
    Spring préconise une démarcation des transactions au niveau des interfaces métier.
    donc c pas en faveur des hibernate template (que je trouve horrible d'ailleurs)

    par contre je ne savais pas qu'il n'est pas conseillé d'utiliser les transaction dans la dao, mais au final c logique, car c uniquement la couche métier qui appelle les dao...

    par contre ca n'explique pas pourquoi ca marchait avant!

    merci de la remarque

  8. #8
    Membre averti
    Inscrit en
    Août 2005
    Messages
    352
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 352
    Points : 427
    Points
    427
    Par défaut
    8.6. Choosing between programmatic and declarative transaction management

    Programmatic transaction management is usually a good idea only if you have a small number of transactional operations. For example, if you have a web application that require transactions only for certain update operations, you may not want to set up transactional proxies using Spring or any other technology. Using the TransactionTemplate may be a good approach.

    On the other hand, if your applications has numerous transactional operations, declarative transaction management is usually worthwhile. It keeps transaction management out of business logic, and is not difficult to configure in Spring. Using Spring, rather than EJB CMT, the configuration cost of declarative transaction management is greatly reduced.
    Les templates (hibernate, transaction, jdbc, jdo, toplink...) dans Spring utilisent une approche commune basée sur l'utilisation de callback (un cas particulier du pattern Strategy).

    Citation Envoyé par mauvais_karma
    donc c pas en faveur des hibernate template (que je trouve horrible d'ailleurs)
    Tu parles vraiment d'HibernateTemplate ou de TransactionTemplate ?

  9. #9
    Membre habitué
    Inscrit en
    Décembre 2002
    Messages
    186
    Détails du profil
    Informations forums :
    Inscription : Décembre 2002
    Messages : 186
    Points : 130
    Points
    130
    Par défaut
    It keeps transaction management out of business logic,
    quand je lis ca je comprend que les transaction déclarative c bien car pas intrusif pour le code métier. Ca veut pas dire que c mal de le mettre dans le code des dao? (cela dit, tu m'as convaincu que c inutile)

    Tu parles vraiment d'HibernateTemplate ou de TransactionTemplate ?
    les 2, mais je pensais en particulier aux HibernateTemplate qui gerent les transaction automatiquement

  10. #10
    Membre averti
    Inscrit en
    Août 2005
    Messages
    352
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 352
    Points : 427
    Points
    427
    Par défaut
    Comment se passe la gestion des transactions avec HibernateTemplate :
    - si tu es dans une transaction, les opérations dans hibernate se font dans le cadre de cette transaction. La transaction n'est pas commitée par HibernateTemplate.
    - si tu n'es pas dans une transaction, on en crée une nouvelle, tes opérations se font dans la transaction et elle est ensuite commitée par HibernateTemplate.

    Je ne vois rien dans le commentaire que j'ai écrit en défaveur d'HibernateTemplate. Par contre, j'aurais tendance à éviter le plus possible TransactionTemplate (gestion programmatique des transactions).

  11. #11
    Membre habitué
    Inscrit en
    Décembre 2002
    Messages
    186
    Détails du profil
    Informations forums :
    Inscription : Décembre 2002
    Messages : 186
    Points : 130
    Points
    130
    Par défaut
    bon je crois que je vais finir par acheter le bouquin que tu m'as conseillé

    sinon g pas dit que tu étais contre hibernatetemplate, g dit que gt d'accord avec toi pour gérer les transactions au niveau métier et pas dao, donc par extension, je me disais que les hibernateTemplate qui gere les transaction pour les dao sont inutiles si on sépare bien les couches dao et métier.

  12. #12
    Membre averti
    Inscrit en
    Août 2005
    Messages
    352
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 352
    Points : 427
    Points
    427
    Par défaut
    En fait, tu ne dois pas voir HibernateTemplate uniquement comme un moyen de gérer les transactions. Tu peux utiliser cette classe comme helper pour :
    - convertir les exceptions hibernate en DataAccessException
    - utiliser un template pour l'execution d'un callback (pas de gestions des sessions et autres ressources à faire)
    - utiliser son interface pour faciliter l'accès à hibernate
    - assurer la cohérence avec le reste de ton appli si elle utilise Spring

    Lis la javadoc pour plus d'infos.
    Je t'ai conseillé quel bouquin ? Si tu veux comprendre la philosophie derrière Spring, il faut absolument lire Expert One-On-One J2Ee Design and Development. Tu comprendras alors l'explication de ces templates et de ces callbacks.
    Si tu veux tout savoir sur Spring, regarde Professional Java Development With The Spring Framework. Je te conseille également Pro Spring qui a l'air bien complet (je ne l'ai pas lu par contre).

  13. #13
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    144
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2005
    Messages : 144
    Points : 95
    Points
    95
    Par défaut
    Bonjour,

    j'ai un problème similaire, je ne sais pas comment catché proprement mes exceptions.
    J'utilise JTA avec 2 datasources. Au niveau service j'ai donc un proxy JTA qui gère mes services.
    Je sais que HibernateTemplate au niveau de mes DAO définit des unchecked dataacessexception et qu'il ne faut pas les catché car c'est le proxy qui va s'en charger pour savoir si oui ou non il est nécessaire de rollbacker la transaction (selon l'état des datasources). Donc, comment faire pour tout simplement catcher l'exception ? si je la catch dans le service, est que le rollback se fera quand meme ?

    merci

  14. #14
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2005
    Messages
    144
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2005
    Messages : 144
    Points : 95
    Points
    95
    Par défaut
    en fait, je vais simplifier ma question je pense :
    est ce que je peux catcher l'exception DataAccessException retournée par la couche DAO, sans interférer avec le service proxy jta ?
    si oui c'est nickel, le rollback s'opère, je trace l'erreur dans le logs et je renvoi l'utilisateur vers une page d'erreur
    sinon, bah... je sais pas comment faire help

Discussions similaires

  1. [Data] Spring - Hibernate => Transactions
    Par Flam dans le forum Spring
    Réponses: 3
    Dernier message: 05/06/2012, 17h24
  2. [Data] Problème gestion transactions spring/hibernate
    Par Reno17 dans le forum Spring
    Réponses: 4
    Dernier message: 04/02/2010, 15h36
  3. [Framework] Challenge ! Spring + Hibernate = double transaction ?
    Par benett31 dans le forum Spring
    Réponses: 2
    Dernier message: 22/10/2009, 10h19
  4. [Data] Problème de transaction Spring Hibernate
    Par totoz dans le forum Spring
    Réponses: 0
    Dernier message: 01/07/2009, 16h21
  5. Hibernate-Spring Aucune transactions
    Par Takis dans le forum Hibernate
    Réponses: 6
    Dernier message: 17/04/2009, 11h31

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