-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 15 posts ] 
Author Message
 Post subject: Hibernate gère les transactions ou pas ???
PostPosted: Mon Sep 05, 2005 6:20 am 
Regular
Regular

Joined: Sat May 15, 2004 4:27 am
Posts: 79
Bonjour,

1 - )
ne réussissant pas à avoir les réponses que j'attends, je reposte. Par défaut
est-ce que Hibernate gère les transactions concourantes ou pas ? Je crois
savoir par défaut qu'il se repose sur la stratégie d'isolation offerte par le
SGBDR. Dois-je comprendre que la gestion des accès concourantes doit
être gérée par le developpeur lui-même soit par verrouillage pessimiste ou
ou optimiste ?

Merci de me répondre.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 05, 2005 6:28 am 
Pro
Pro

Joined: Fri Sep 02, 2005 4:21 am
Posts: 206
Location: Vienna
Bonjour,

Je crains fort (pour ne pas dire: je suis certain) que ces problèmes sont laissés à la discrétion du développeur...

Erik


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 05, 2005 7:36 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
Il faut plusieurs pages pour répondre correctement à tes questions, je te recommande de relire la doc de référence et un livre (Hibernate In Action ou Hibernate 3.0) pour plus d'explications.

La gestion des transactions en tant que telles est déléguée à ton SGBDR, de la même manière que tes accès à une connexion JDBC le sont. Autrement dit, l'équipe Hibernate n'a pas implémenté de système de verrou pessimistes en mémoire parce qu'elle croit que les vendeurs de SGBD on une bien meilleure expérience/granularité possible que les développeurs de middleware.
La gestion des transactions utilisateur concurrentes est donc guaranti par design, une session étant associée au travail d'un utilisateur et isolée au sein d'une transaction de base de données. L'application n'ayant qu'à délimiter correctement ses transactions pour se garantir l'isolation voulue.

Afin de gérer la notion d"objet détaché sans perdre l'isolation trasnactionnelle, Hibernate implémente le mécanisme de lock optimiste (en général un n° de version incrémenté mais il existe d'autres stratégies). Hibernate se charge de la comparaison de ce n° de version et de son incrément de manière transparente pour l'application.

Il est possible de poser des lock pessimistes plus forts que le niveau d'isolation transactionnel choisi en utilisant certaines API d'hibernate. Mais cette mécanique est rarement utile (parce que ne scalant pas bien).

Ceci n'est qu'un tableau général, la lecture d'un bouquin est fortement recommandée ( PS, il faut bien choisir ses auteurs, parce que tout le monde ne comprend pas bien ces choses là ;-), et pas mal de bêtises ont été publiées )

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 05, 2005 8:41 am 
Regular
Regular

Joined: Sat May 15, 2004 4:27 am
Posts: 79
@emmanuel

J'ai les trois bouquins. Celui d'anthony, même si je travaille en Hibernate
2.1.6. C'est pas grave. Il est trés bien. Et celui de Christian & Gavin (en
français et en anglais).

C'est bien ce que j'avais compris. Mais cette réponse me conforte car
elle est en accord avec mes propos. Tout le monde (dans mon équipe ) s'étonnes qu'Hibernate ne fasse pas comme les CMP.

Je me pose donc la question de savoir comment faire pour gérer mes
accès concurrents car contrairement à tous les exemples que je vois, mon
application n'est pas orientée utilisateurs. C'est pas une servlet mais une
appli java classique qui tourne sur Jboss.

Un thread fait appel à un web service pour enregistrer ou modifier des
infos. Et d'autres threads peuvent aussi faire la même chose. D'où mon
problème de concurrence.

A quel niveau dois-je agir pour synchroniser l'accès à mon module ? Je ne
vois pas non plus pourquoi j'ai ce problème ? Puisque ma transaction A
démarre avant ma transaction B. Je valide ma transaction A avant B mais
en dépit de ça, j'ai des StaleObjectException ???

Est-ce que ma configuration peut-être en cause. J'utilise un MBean qui est
le suivant :

<server>
<mbean code="net.sf.hibernate.jmx.HibernateService" name="jboss.jca:service=HibernateFactory,
name=HibernateFactory">
<depends>jboss.jca:service=RARDeployer</depends>
<depends>jboss.jca:service=LocalTxCM,name=OracleDS</depends>
<attribute name="MapResources">MAPPINGS ICI
<attribute name="JndiName">java:/hibernate/HibernateFactory</attribute>
<attribute name="Datasource">java:/OracleDS</attribute>
<attribute name="Dialect">net.sf.hibernate.dialect.Oracle9Dialect</attribute>
<attribute name="TransactionStrategy">net.sf.hibernate.transaction.JTATransactionFactory</attribute>
<attribute name="TransactionManagerLookupStrategy">net.sf.hibernate.transaction.JBossTransactionManagerLookup</attribute>
<attribute name="ShowSql">false</attribute>
<attribute name="UserTransactionName">UserTransaction</attribute>
</mbean>
</server>

Dois-je utiliser JDBCTransactionFactory au lieu de JTA par exemple ?

Je pense que la meilleur solution serait qu'une transaction B démarre
SEULEMENT apres que la transaction A ait été validée (commitée ses
modifications dans la base de données). Est-ce qu'Hibernate m'offre
un moyen de savoir qu'une transaction a été validée et que les
modifications ont été prises en compte par le SGBDR (Oracle 9i) ?

Je sais que c'est beaucoup de questions mais je cherche à comprendre.

Dernière chose. Dans une application 'classique' comme la mienne
comment puis-je faire pour mettre en place un objet (genre mémoire
partagée) similaire au httpSession. Dans le bouquin d'Anthony et les
autres ils font appel au httpSession pour garder la session dans les
transactions longues. Ne voulant pas transformer mon application en
y mettant un EJB session qui puisse me faire ça, je cherche d'autres
solutions...


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 05, 2005 1:46 pm 
Pro
Pro

Joined: Fri Sep 02, 2005 4:21 am
Posts: 206
Location: Vienna
@smayemba,

Ce n'est certes pas une réponse directe, mais cela peut éventuellement être utile: Spring offre de riches possibilités pour la gestion des transactions.

Cela vaut à mon avis un coup d'oeil - nous avons utilisé cette constellation dans un projet industriel où les exigences tant en matière de performance que de sécurité étaient très élevées.

Erik


Top
 Profile  
 
 Post subject:
PostPosted: Mon Sep 05, 2005 2:42 pm 
Regular
Regular

Joined: Sat May 15, 2004 4:27 am
Posts: 79
@ErikFK

Oui en effet, je ne me suis pas encore fait la main sur Spring, mais en effet
j'ai vu que ce Framework offre des choses assez sympas. Je ne veux pas
du tout réinventer la roue en me mettant a essayer de synchroniser l'accès
des autres modules.

Je cherche à savoir si y'a pas un pattern qui existe déja pour ce genre de problème
de concurrence. Et si vraiment y'a pas. Je verrai si je suis obligé d'utiliser Spring ou
gérer moi même (enfin essayé) les accès.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 06, 2005 6:57 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
smayemba wrote:
Tout le monde (dans mon équipe ) s'étonnes qu'Hibernate ne fasse pas comme les CMP.

C'est pour ça qu'Hibernate marche et pas les CMP ;o)
Plus sérieusement, c'est pour ça que dans les EJB3.0, les CMP sont abandonnés pour une approche à la Hibernate. Il faut bien comprendre que les objets attachés à une session ne sont visibles que d'un seul thread contrairement aux CMPs, donc pas de besoin de synchronisation.

smayemba wrote:
A quel niveau dois-je agir pour synchroniser l'accès à mon module ? Je ne
vois pas non plus pourquoi j'ai ce problème ? Puisque ma transaction A
démarre avant ma transaction B. Je valide ma transaction A avant B mais
en dépit de ça, j'ai des StaleObjectException ???


Si je comprend bien,
le process A est lancé, il lit des données
le process B est lancé, il lit des données
le process A commite des changements
le process B commite des clangements

Tu as des exceptions parce que quand B essaie de commiter, elle utilise des données périmées puisque changées par A. Si ce scénario arrive rarement (et il devrait puisque le process ne devrait pas garder des connections à la DB trop longtemps), il faut laisser l'utilisateur résoudre le conflit ou le reprendre applicativement Si tu veux que le dernier ait toujours raison, il suffit de ne pas faire de gestion optimiste, la Tx B ecrasera la Tx A. Si tu veux que A finisse son travaille avant que B lise, tu doit poser un lock sur un objet commun (par exemple avec session.get(MaClasseCommune.class, id, LockMode.UPGRADE); )
A ce moment là, c'est ta base de données qui gère les locks mais cela scale moins.
Troisième solution, tu exécutes ton appel de service dans un block synchronize mais une seule personne à la fois peut accéder au service.

Ton isolation dépend de ton besoin et n'a rien à voir avec la technologie sous jacente.

smayemba wrote:
Je pense que la meilleur solution serait qu'une transaction B démarre
SEULEMENT apres que la transaction A ait été validée (commitée ses
modifications dans la base de données). Est-ce qu'Hibernate m'offre
un moyen de savoir qu'une transaction a été validée et que les
modifications ont été prises en compte par le SGBDR (Oracle 9i) ?


Non, et personne ne le peut à part Oracle DB. Quelqu'un pourrait accéder à ta base de données dans une autre application et contrecarrer les locks stockées en Java (tiens, je viens d'expliquer pourquoi les locks CMP n'étaient pas une bonne solution).

Mais la solution avec le bloc synchronisé est ce que tu viens de décrire.

Quote:
Dernière chose. Dans une application 'classique' comme la mienne
comment puis-je faire pour mettre en place un objet (genre mémoire
partagée) similaire au httpSession. Dans le bouquin d'Anthony et les
autres ils font appel au httpSession pour garder la session dans les
transactions longues. Ne voulant pas transformer mon application en
y mettant un EJB session qui puisse me faire ça, je cherche d'autres
solutions...

Une HashMap statique synchronisée.
Transaction longue == gestion des lock optimistes.

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 06, 2005 7:04 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
ErikFK wrote:
Ce n'est certes pas une réponse directe, mais cela peut éventuellement être utile: Spring offre de riches possibilités pour la gestion des transactions.

Spring ne résout pas le problème décrit. La gestion des Tx de Spring est:
- une abstraction des Tx JDBC ou JTA => Hibernate l'offre déjà
- une gestion déclarative des frontières de transactions ce que font les EJBs mais hors d'un container (PS les EJB 3 feront ça).

Pour ce qui est de la gestion des locks pessimistes ou optimistes, Spring est agnostique

Il se peut que Spring gère la notion de composant singleton ou a accès exclusif, mais je ne vois pas l'intéret d'ajouter un framework et une config xml qui va se contenter d'utiliser un bloc synchronize, autant utiliser ce bloc soit-même. Ca prend 3 lignes de code.

Spring est utile, mais pas spécialement pour résoudre ce cas particulier.

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 06, 2005 9:05 am 
Regular
Regular

Joined: Sat May 15, 2004 4:27 am
Posts: 79
@emmanuel & @ErikFK

un grand merci à tout les deux. Je suis un peu dans l'urgence. Je vais
m'orienter vers la solution des locks pessimistes. Lorsque j'aurai moins
de pression je reviendrai faire des modifications pour une solution avec
des synchronized. Il m'est impossible d'implémenter une solution avec
des vérrous optimistes car y'a pas d'utilisateur. Les web services sont
émis par des automates (des threads) localisés. On est dans une
architecture totalement distribuée.

Le coup du HashMap statique synchronisée je n'y avais pas du tout
penser. Je vais voir.

Merci les gars...


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 06, 2005 9:52 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
Tu peux utiliser des lock optimistes avec autre chose que des utilisateurs, ce n'est pas lié.
D'ailleurs oracle implémente ses stratégies d'isolations avec quelque chose qui ressemble à des verrous optimistes.

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 06, 2005 12:59 pm 
Regular
Regular

Joined: Sat May 15, 2004 4:27 am
Posts: 79
N'ayant pas d'utilisateur, je ne vois pas trop comment je pourrais faire
pour corrige les StaleObjectException. Je dois ABSOLUMENT garantir
que la demande d'insertion faite par l'automate a bien été prise en
compte.

Si ma version change. Je ne vois pas trop comment faire pour gérer
le conflit. D'où justement une gestion des accès. Ne pas accèder à la
base tant que celle-ci n'est pas disponible pleinement pour un et un
seul automate à la fois.

Cette soluton soulève aussi d'autres problèmes. Je dois implémenter
un FIFO. Si la l'automate B arrive avant le C et qu'il attend son tour.
B doit est le suivant à utiliser la base lorsque celle-ci est disponible.

Bref c'est pas gagné.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Sep 07, 2005 4:38 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
Si la version change sur des données que tu viens de lire dans ta transaction (genre 1/2 sec avant), tu la relances entièrement, pas besoin d'utilisateurs.

Si la version change parce que c'est ton automate (système extérieur) qui a donné une version obsolète, tu as un problème. Tes données sont incohérentes, et enlever le lock optimiste ne va pas résoudre le problème, cela va le cacher.

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Wed Sep 07, 2005 7:01 am 
Regular
Regular

Joined: Sat May 15, 2004 4:27 am
Posts: 79
Mon automate ne donne pas de numéro de version. Il fait appel à un
service dans lequel je fais des traitements sur la base. Je lis donc
des données. Mais ce service web, un autre automate peut aussi l'
appeler. Donc probleme.

Tu parles de relancer la transaction. Il s'agit en fait de catcher le
StaleObjectException et refaire entièrement le traitement ? Ou est-ce
qu'hibernate peut rejouer une transaction définie, échouée ???


Top
 Profile  
 
 Post subject:
PostPosted: Wed Sep 07, 2005 8:00 am 
Regular
Regular

Joined: Sat May 15, 2004 4:27 am
Posts: 79
en fouillant un peu dans la doc. Je constate qu'il existe l'instruction :

select-before-update

vous en pensez quoi ? N'est-ce pas une tricherie si l'on utilise un
verrou optimiste ? Avec ça, est-ce que le numéro de version
change toujours ? Sinon, le verrou optimiste sert-il encore à
quelque chose lorsqu'on utilise cette instruction ?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Sep 09, 2005 6:11 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
tu relance en utilisant une nouvelle session Hibernate.
select-before-update n'a pas d'influence sur le lock optimiste.

_________________
Emmanuel


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 15 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.