# Java > Gnral Java > Persistance des donnes >  [PersistenceContext] Lock timeout seulement avec un EntityManager Extended

## LTourist

Salut,

Je ralise actuellement une application web qui utilise les lib suivantes (pour rfrence) : 
Hibernate (3.5.6)Spring (3.0.5)JSF (2.1.1-b03)MySQL (5.5.10)mysql-connector-java (5.1.9)c3p0 (0.9.1.2)

Le tout sur un Tomcat 7.0.14  ::): 

Depuis quelques temps, je me tapais des lock wait timeout, mais jusqu' prsent, j'avais russi  les contourner. Mais cette fois...  ::roll:: 

Hier, j'ai dcouvert quelque chose d'intressant, ces dead lock n'arrivent que lorsque mon EntityManager est annot avec PersistenceContextType en Extended. Lorsque celui-ci est en Transaction, plus de problme du tout !!!

*Premire question :* Meuh pourquoi a change quelque chose sur ce point ???  :8O: 

Du coup au dbut, je me dis facile, je met l'EntityManager en Transaction et roulez jeunesse ! J'ai donc utilis OpenEntityManagerInViewFilter pour ne plus avoir de LazyInitializationException. Tout se passe bien cot front (couche de prsentation JSF), mais lorsque je tente de modifier une liste lazy cot service : Bim! De nouveau LazyInitizalizationException : pas de proxy ou session ferme.

A savoir que tous mes services sont marqus comme tant Transactionnal.
*Deuxime question :* Donc normalement, la session ne devrait pas tre ferme, non ?

Le dead lock (enfin c'est un lock timeout en fait) apparait lorsque je fais ce genre de modif :
Code:


```

```

Pour info, les relations sont dfinies dans les entits de cette manire :
Car :


```

```

Wheel :


```

```

Le truc bizarre, et que je vois MySQL qui semble locker l'enregistrement correspondant  c sur la dernire ligne (celle avec la flche). Et au bout de 50 secondes qu'il n'a pas russi  obtenir ce lock, il dgage (c'est le seul verrou qui apparat dans MySQL).

Donc voil. Honntement, je n'en peux plus, je crois que j'ai tout essay dans tout les sens, et c'est totalement bloquant pour la suite de mon projet. Qui plus est, ce genre de bloquage se retrouve  de nombreux endroits dans l'application... Je dois donc me planter quelque part de faon monumentale, mais o ?  ::aie:: 

LTourist

----------


## LTourist

Pour info, j'ai rcupr les logs de MySQL, et repris toutes les requtes qui constituent ma procdure. Lorsque je les mets dans un script et les excute, il n'y a aucun blocage...  :8O: 

Le blocage peut-il venir du cot Hibernate/JPA seulement ???

----------


## LTourist

Un peu de neuf :
Le lock timeout intervient car les deux requte create sont excutes dans deux transactions diffrentes. Donc la deuxime attend la fin de la premire pour faire son insert ( cause de la fk, elle doit lire l'enregistrement lock par la premire transaction).

Le problme est que toute ces mthodes sont marques comme propagation = Propagation.REQUIRED, ce qui devrait faire l'ensemble de la procdure dans une seule transaction. Force est de constat que ce n'est pas le cas...

Quelqu'un saurait-il  quoi c'est d, et ventuellement comment rsoudre a ? (REQUIRED = une seule transaction, pas 56!!!)

EDIT : les diffrentes transactions JPA se rejoignent bien, cependant, plusieurs connexions sont prises dans le pool (c3p0) et ouverte dans MySQL. Ce mode de fonctionnement est normal dans JPA, mais ne devrait-il pas y avoir autant de transaction cot JPA que MySQL ?

----------


## -gma-

Bonjour,

D'aprs la doc de l'API:


```

```

Donc si une transaction existe il la rutilise mais sinon il en dmarre une nouvelle.

Si ce sont des mthodes de Service qui sont annotes avec  @Transactional (je fais une hypothse) et que c'est un contrleur qui appelle ces diffrentes mthodes mais que ce contrleur n'est pas "@Transactional" alors on risque en effet de se retrouver avec des transactions spares.

Si une mthode s'attend  ce qu'une transaction soit dj en cours lorsqu'elle est appele alors il vaut mieux utiliser MANDATORY

----------


## LTourist

> Bonjour,
> 
> D'aprs la doc de l'API:
> 
> 
> ```
> 
> ```
> 
> ...


Merci de ta rponse.
Tous mes services sont annots @Transactional, ainsi que mes DAO. Les premiers sont REQUIRED tandis que les DAO sont MANDATORY justement.

Le point d'entre de ma procdure se trouve dans un service, et la transaction est donc bien dmarre.

Comme je l'ai mis au dessus, je pense que le problme vient plus d'une fait que lorsqu'une transaction est dmarr et rejoins la transaction existante, une nouvelle connection est tout de mme prise dans le pool et ouverte avec MySQL (avec sa propre transaction, qui du coup produit le lock timeout).

Ce mode de fonctionnement ressemble beaucoup  http://dev.mysql.com/doc/refman/5.5/en/xa.html, mais j'ai beau cherch, tout semble compatible avec ce mode dans ma chaine de connection  la BDD... A part peut etre c3p0, sur lequel je ne trouve pas d'infos concernant ce mode...


On peut voir dans ce log le nombre de connections inutilises baisser, a chaque fois, une nouvelle connection est ouverte dans MySQL (c'est un gros pav je sais, mais si a peut aider) :



> 17 juin 2011 05:09:39 [main] org.springframework.orm.jpa.JpaTransactionManager - Creating new transaction with name [gpaf.services.impl.UserService.find]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT; ''
> 17 juin 2011 05:09:39 [main] org.springframework.orm.jpa.JpaTransactionManager - Opened new EntityManager [org.hibernate.ejb.EntityManagerImpl@15d4273] for JPA transaction
> 17 juin 2011 05:09:39 [main] com.mchange.v2.resourcepool.BasicResourcePool - trace com.mchange.v2.resourcepool.BasicResourcePool@5d855f [managed: 5, *unused: 4*, excluded: 0] (e.g. com.mchange.v2.c3p0.impl.NewPooledConnection@1758cd1)
> 17 juin 2011 05:09:39 [main] org.springframework.orm.jpa.JpaTransactionManager - Exposing JPA transaction as JDBC transaction [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@15c6c8d]
> 17 juin 2011 05:09:39 [main] com.mchange.v2.resourcepool.BasicResourcePool - trace com.mchange.v2.resourcepool.BasicResourcePool@5d855f [managed: 5, *unused: 3*, excluded: 0] (e.g. com.mchange.v2.c3p0.impl.NewPooledConnection@1758cd1)
> 17 juin 2011 05:09:39 [main] org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler - Starting resource local transaction on application-managed EntityManager [org.hibernate.ejb.EntityManagerImpl@17cff66]
> 17 juin 2011 05:09:39 [main] org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler - Joined local transaction
> 17 juin 2011 05:09:39 [main] org.hibernate.SQL - select user0_.ID as ID3_0_, user0_.droits as droits3_0_, user0_.hibernate_version as hibernate3_3_0_, user0_.login as login3_0_, user0_.password as password3_0_ from user user0_ where user0_.ID=?
> 17 juin 2011 05:09:39 [main] com.mchange.v2.c3p0.stmt.GooGooStatementCache - cxnStmtMgr.statementSet( com.mysql.jdbc.JDBC4Connection@1195c2b ).size(): 1
> ...

----------


## JeitEmgie

jettez un coup d'il sur cette discussion du forum jboss, il y a peut-tre un lment qui vous clairera.

----------


## LTourist

> jettez un coup d'il sur cette discussion du forum jboss, il y a peut-tre un lment qui vous clairera.


Merci de la rponse, mais malheureusement a ne m'aide pas beaucoup, vu que d'aprs les logs, les join transaction & ie se font correctement... le problme vient donc certainement de plus bas... Je pense notamment aux drivers MySQL ou  MySQL en lui-mme (a serait gros, mais je vois pas d'autres solutions  ::(:  )

----------


## JeitEmgie

> Merci de la rponse, mais malheureusement a ne m'aide pas beaucoup, vu que d'aprs les logs, les join transaction & ie se font correctement... le problme vient donc certainement de plus bas... Je pense notamment aux drivers MySQL ou  MySQL en lui-mme (a serait gros, mais je vois pas d'autres solutions  )


MySQL ne gre pas les transactions imbriques et la discussion du forum en rfrence fait allusion  des incompatibilits entre EXTENDED et le mode de gestion de la session stateless/stateful  cause justement des frontires de transaction :  donc quand vous dtes que le problme est sans doute "plus bas", ce n'est pas faux, mais peut-tre pas pour une question de "bug" dans le driver JDBC  mais tout simplement de fonctionnalit limite du RDBMS

----------


## LTourist

> MySQL ne gre pas les transactions imbriques et la discussion du forum en rfrence fait allusion  des incompatibilits entre EXTENDED et le mode de gestion de la session stateless/stateful  cause justement des frontires de transaction :  donc quand vous dtes que le problme est sans doute "plus bas", ce n'est pas faux, mais peut-tre pas pour une question de "bug" dans le driver JDBC  mais tout simplement de fonctionnalit limite du RDBMS


MySQL gre les transactions imbriques, voir le lien du post prcdent  :;):  (enfin transactions distribues=transactions imbriques non ?) Je comptais justement tester le tout sur une base Oracle pour voir si a fonctionnait mieux.

J'ai toujours eu du mal avec les histoires stateless/statefull (c'est aussi pour a que je voyais pas trop le rapport avec mon problme) mais il me semblait que c'tait rserv lors de l'utilisation d'EJB ?

----------


## JeitEmgie

> MySQL gre les transactions imbriques, voir le lien du post prcdent  (enfin transactions distribues=transactions imbriques non ?) Je comptais justement tester le tout sur une base Oracle pour voir si a fonctionnait mieux.
> 
> J'ai toujours eu du mal avec les histoires stateless/statefull (c'est aussi pour a que je voyais pas trop le rapport avec mon problme) mais il me semblait que c'tait rserv lors de l'utilisation d'EJB ?


par transaction imbriques, j'entends 


```

```

sur la *mme* connection (ce que devrait faire un "vrai" REQUIRES_NEW)

une transaction distribue c'est une transaction qui concerne plusieurs ressources

----------


## LTourist

OK, je pensais que a revenait au mme... Ce que vous dcrivez ici revient  ce que fait justement mon REQUIRED, et c'est justement ce que je voudrais viter (puisque ce qui est fait dans la deuxime transaction n'est pas visible par la premire).

Je suis en train de passer sur Oracle, voir si le problme est rsolu avec ce SGBD.

----------


## LTourist

Passer la base sur Oracle a rsolu le problme  ::ccool:: 
Pas "normal", mais bon au moins a marche

----------


## LTourist

Bon quelques news un peu tardive, mais a peut tre utile  d'autre.

Le problme venait certainement en fait d'une utilisation d'un PersistenceContext en EXTENDED hors d'un contexte J2E (j'utilise Tomcat) et inject par Spring.

Dans ce cas, Spring semble injecter un PersistenceContext diffrent par DAO, ce qui fait qu'entre deux DAO, le cache de niveau 1 de JPA/Hibernate n'est pas partag.

Bien sur a peut tout de meme fonctionner si la session est flush dans la 1ere DAO avant d'appeler la seconde, puisque dans ce cas, le cache de niveau 2 est actualis...

Aprs au niveau des locks peut etre que du meme coup ils y a d'autres trucs qui s'embrouillent du fait de cette mauvaise gestion.

Pour rfrence : http://favit.com/d/294U2/bozhos-tech-blog-spring-and

----------

