OVH Cloud OVH Cloud

[ Servlet et Hibernate ] Accès concurrents

2 réponses
Avatar
Jim How
Bonjour,

Auriez-vous une réponse à apporter à mon problème.

Le voici, imaginons que je créé une WebApp (servlets) pour tomcat qui se
sert d'Hibernate pour la persistance des données.

Si j'en crois la doc française d'hibernate, ils conseillent de faire une
Session (DAO pas web) par requette.
Pour cela, ils recommandent de créer un singleton créant une SessionFactory
(je suis les exemples basiques de la doc).

Chaque fois qu'on appelle le servlet avec une requette, ce singleton fournit
un "pointeur" sur la Session (DAO toujours) courrante.
A la fin de la requette la session est flushé pour assurer la persistance.

C'est ce que j'ai essayé de faire, seulement soit je suis con et j'ai oublié
un truc, soit y a une coquille dans leur copie.

Quand deux requettes (pas besoin de plus) sont rapprochées au point que, le
pointeur de "session" de la deuxième requette est encore en activité quand
le premier "pointeur" flush, cela génére des erreurs (LazyException et tout
le bordel).

Vu que le singleton retourne toujour un pointeur sur la session courrante,
mon cerveau à beau turbiné à son maximum, je vois pas comment on pourrait
eviter ce genre de problème.

De plus, mais cela me gène moins, vu que l'on flush à chaque requette la
session hibernate on est sencé perdre tout les bénéfices du cache de segond
niveau si je ne me trompe pas.

J'y reflechis depuis un petit peu de temps, je trouve des solutions
"tordues" pour pallier au problème, mais j'en reviens à une question qui
m'obséde "il doit bien y avoir quelque chose que les autres font et que je
ne fait pas pour ne pas avoir ce probleme".

Des centaines de sites, voir des milliers, sont sur une architecture
identique, alors pourquoi moi j'ai une solution bancale et eux une WebApp
fiable à 100%. Et je ne pense pas que tous les utilisateurs d'hibernate
l'utilise en environnement J2EE ou avec un JTA.


Si quelqu'un à un debut de piste, une réponse, un tutorial à me proposer
(autre que les cons de copier/coller de la doc francaise d'hibernate), je
suis preneur.


Merci de votre interet et participation :)

Jim

2 réponses

Avatar
simon.oualid
Bonjour,

Je ne suis pas retourné vérifier la doc, mais je crois qu'ils
préconisent une SessionFactory globale (référencée par un
singleton), qui fournit bien *une* session distincte par requête
nécessitant l'exploitation de la couche DAO.

Ca semble logique quand on sait que la SessionFactory est "longue" à
construire, alors que les sessions sont très rapides à créer.

Je crois d'ailleurs que c'est ce que fait l'implementation par défaut
de SessionFactory, puisque les sessions sont bindés sur le thread qui
a demandé la session.

Donc, plus de problèmes d'accès concurrents. Par contre, le cache de
second niveau n'est effectivement pas utilisé dans un tel
environnement.

Après je bosse pas énormément en environnement web, tout ça reste
donc à vérifier... ^_^

Simon

Jim How wrote:
Bonjour,

Auriez-vous une réponse à apporter à mon problème.

Le voici, imaginons que je créé une WebApp (servlets) pour tomcat qui se
sert d'Hibernate pour la persistance des données.

Si j'en crois la doc française d'hibernate, ils conseillent de faire une
Session (DAO pas web) par requette.
Pour cela, ils recommandent de créer un singleton créant une SessionF actory
(je suis les exemples basiques de la doc).

Chaque fois qu'on appelle le servlet avec une requette, ce singleton four nit
un "pointeur" sur la Session (DAO toujours) courrante.
A la fin de la requette la session est flushé pour assurer la persistan ce.

C'est ce que j'ai essayé de faire, seulement soit je suis con et j'ai o ublié
un truc, soit y a une coquille dans leur copie.

Quand deux requettes (pas besoin de plus) sont rapprochées au point que , le
pointeur de "session" de la deuxième requette est encore en activité quand
le premier "pointeur" flush, cela génére des erreurs (LazyException e t tout
le bordel).

Vu que le singleton retourne toujour un pointeur sur la session courrante,
mon cerveau à beau turbiné à son maximum, je vois pas comment on po urrait
eviter ce genre de problème.

De plus, mais cela me gène moins, vu que l'on flush à chaque requette la
session hibernate on est sencé perdre tout les bénéfices du cache d e segond
niveau si je ne me trompe pas.

J'y reflechis depuis un petit peu de temps, je trouve des solutions
"tordues" pour pallier au problème, mais j'en reviens à une question qui
m'obséde "il doit bien y avoir quelque chose que les autres font et que je
ne fait pas pour ne pas avoir ce probleme".

Des centaines de sites, voir des milliers, sont sur une architecture
identique, alors pourquoi moi j'ai une solution bancale et eux une WebApp
fiable à 100%. Et je ne pense pas que tous les utilisateurs d'hibernate
l'utilise en environnement J2EE ou avec un JTA.


Si quelqu'un à un debut de piste, une réponse, un tutorial à me pro poser
(autre que les cons de copier/coller de la doc francaise d'hibernate), je
suis preneur.


Merci de votre interet et participation :)

Jim


Avatar
jeje900ss
Jim How wrote:
Bonjour,


Bonjour,


Auriez-vous une réponse à apporter à mon problème.

Le voici, imaginons que je créé une WebApp (servlets) pour tomcat qui se
sert d'Hibernate pour la persistance des données.

Si j'en crois la doc française d'hibernate, ils conseillent de faire une
Session (DAO pas web) par requette.
Pour cela, ils recommandent de créer un singleton créant une SessionFactory
(je suis les exemples basiques de la doc).

Chaque fois qu'on appelle le servlet avec une requette, ce singleton fournit
un "pointeur" sur la Session (DAO toujours) courrante.
A la fin de la requette la session est flushé pour assurer la persistance.

[...]



Si quelqu'un à un debut de piste, une réponse, un tutorial à me proposer
(autre que les cons de copier/coller de la doc francaise d'hibernate), je
suis preneur.



En fait il faut lier une Session par requête.
Le Singleton permet d'avoir une seul instance du SessionFactory, mais
ensuite il te faut lier toute nouvelle Session créer avec la Requête
utilisateur en cours.
Etant donné que chaque requête utilisateur est traité par un Thread
différent, il faut utiliser un ThreadLocal (il me semble que c'était
expliqué dans la doc hibernate).

Normalement Hibernate 3 gère tout seul ceci, il suffit de rajouter
<!-- Bind the getCurrentSession() method to the thread,
session-per-thread -->
<property name="current_session_context_class">thread</property>

dans le fichier de conf.

Jérôme