2010-10-20 10 views
3

Disons que j'ai méthodes avec après la signatured'accès simultané (données périmées) dans JPA

Object getData(int id) { 
    //create a entity manager 
    //get data frm db 
    //return data 
} 

updateData() { 
    Object obj = getData(id) 
    //get entity manager 
    //start transcation tx 
    //update 
    //commit tx 
} 

Maintenant, il va causer problème de concurrence? Les données peuvent-elles être périmées dans le pire des cas? Par exemple. si je getData et au moment où je mets à jour, si quelqu'un met à jour les données mon updateData aura des données périmées? Maintenant, puis-je utiliser ce qui suit: Vais-je résoudre le problème?

Object getData(int id,Entitymanager em) { 

     //get data frm db using em 
     //return data 
    } 

updateData() { 
     Object obj = getData(id) 
     //get entity manager em 
     //start transcation tx 
     //getdata using getData(id,em) 
     //commit tx 
    } 

Répondre

5

Oui, cela peut arriver. Si vous obtenez une entité (version 1), quelqu'un d'autre la modifie (créant la version 2), puis vous modifiez la version 1 et l'enregistrez, toutes les modifications dans la version 2 seront perdues.

Pour empêcher cela, utilisez la concurrence optimiste en ajoutant un attribut @Version à votre entité. Si une validation a eu lieu entre votre get et update, une exception sera levée. Au point, vous pouvez choisir votre meilleure option pour y faire face.

0

Il peut également y avoir un problème dans l'environnement multithread, si plusieurs accès au même morceau de code en même temps, il peut créer un verrou, pour cela vous pouvez utiliser la technique de verrouillage au niveau de la ligne, qui vous aidera sur le lien ci-dessous.

http://download.oracle.com/docs/cd/B19306_01/server.102/b14220/consist.htm

+1

Le verrouillage au niveau des lignes n'aidera pas ici: il extrait toutes les données en dehors d'une transaction. – GaryF

+0

va obtenir des données et la mise à jour des données à l'intérieur même transcation va résoudre le problème? Plz voir ma nouvelle édition de l'article original – akp

+0

Obtenir les données à l'intérieur de la transaction signifiera, avec verrouillage de ligne, une mise à jour concurrente d'attendre l'achèvement de la première mise à jour. Cependant, les deux fonctionneront toujours de sorte que votre bloc transactionnel doit veiller à ce qu'il n'écrase rien d'une autre transaction. – GaryF

0

Si deux demandes distinctes en même temps que l'accès updateData() vous pouvez obtenir des données périmées. Vous pouvez gérer la persistance en verrouillant les données récupérées dans updateData(). Si vous utilisez Hibernate comme fournisseur JPA, vous pouvez verrouiller les données comme suit:

updateData() { 
    Object obj = getData(id); 
    Session session = (Session) em.getDelegate(); 
    session.refresh(obj, LockMode.UPGRADE); 
} 

L'actualisation est nécessaire, car il peut arriver que entre le fetching et le verrouillage des données une autre transaction vient compléter dans updateData.

Veuillez garder à l'esprit que le gestionnaire d'entités utilisé dans getData et updateData doit être identique.