2013-03-03 2 views
0

J'ai une question ce qui se passe, si deux utilisateurs différents travaillent sur la même entité. Par exemple. une entité partagée a quatre champs:Hibernate entité partagée conditions de concurrence

class HibernateSharedEntity 
{ 
int id; 
int a; 
int b; 
int c; 
int d; 
} 

Maintenant, les deux utilisateurs ouvrent une transaction en même temps. L'un d'eux met à jour cette entité et le second utilisateur lit cette entité. Les étapes ci-dessous l'expliqueront beaucoup mieux:

Heure 1: L'entité Hibernate est stockée dans la base de données et a des valeurs: a = b = c = d = 0 et id = 1.
Time 2: User1 ouvre une nouvelle transaction.
Heure 3: User1 lit HibernateSharedEntity où id = 1
Time 4: User1 modifie tous les champs: par ex. a = 2, b = 3, c = 4, d = 5.
Heure 5: L'utilisateur 1 valide la transaction.
Heure 6: Hibernate met à jour a = 2
Heure 7: Hibernate est en cours de mise à jour b = 3
Heure 8: maintenant Utilisateur2 ouvre une nouvelle transaction et lit cette entité partagée. Question: Qu'a-t-il récupéré? Est-ce qu'il feteched une entité à moitié mise à jour comme: a = 2, b = 3, c = 0, d = 0?
Temps 9: Mise en veille prolongée est mise à jour c = 4
Temps 10: Mise en veille prolongée est mise à jour d = 5

Je veux éviter les cas demi-jour. C'est un point critique dans mon application. Si le deuxième utilisateur veut récupérer cette entité partagée, je veux que le deuxième utilisateur puisse seulement lire cette entité partagée dans deux états, l'état a = b = c = d = 0 (avant la validation) ou a = 2 , b = 3, c = 4, d = 5 état (après validation). Je sais que hibernate peut faire un insert pour mettre à jour toutes ces valeurs, mais dans mes applications cela semble plus compliqué, parce que cette entité partagée a des relations avec d'autres entités partagées, qui pourraient aussi être mises à jour par User1. Donc, à partir de maintenant, hibernate ne peut pas faire un insert pour mettre à jour ces deux entités partagées. Ainsi, lorsque User1 met à jour plusieurs entités partagées dans une transaction, est-il possible que User2 puisse lire ces entités dans un état non synchronisé, c'est-à-dire lorsqu'une entité est mise à jour, mais qu'une autre entité n'est pas encore mise à jour?

Je pense que cela peut être compliqué alors je vais essayer de l'expliquer beaucoup plus: Dans mon application, les entités partagées doivent être synchronisées. Par exemple. il y a deux entités partagées comme:
entité1 = {a = 1, b = 2, c = 3, d = 4}
entité2 = {a = 5, b = 6, c = 7, d = 8}

et maintenant User1 voulez mettre à jour ces entités par exemple à cet état:
entity1 = {a = 0, b = 0, c = 0, d = 0}
entité2 = {a = 0, b = 0, c = 0, d = 0}

. Alors que User1 effectue une transaction de mise à jour, User2 veut récupérer ces instances partagées et que je veux éviter, que User2 lit ces entités dans cet état:
entity1 = {a = 0, b = 0, c = 0, d = 0}
entity2 = {a = 5, b = 6, c = 7, d = 8}
Comme vous pouvez le voir, entity1 est mis à jour, mais entity2 ne l'est pas. C'est un point critique dans ma demande, et il ne peut y avoir une telle situation. Comment puis-je éviter ça ? Est-ce que hibernate prend soin de cela? Merci d'avance.

Répondre

1

Votre premier scénario est impossible. Hibernate écrit les modifications dans la base de données avant que la transaction ne soit validée, et non après.L'utilisateur 2 lira ce qui a été validé dans la base de données, puisqu'il lit l'entité après que la première transaction a été validée. Si l'utilisateur 2 lisait dans la base de données avant la validation de la première transaction, il lirait l'état tel qu'il était avant le début de la première transaction (tant que le niveau d'isolation de la base de données est la valeur par défaut READ_COMMITTED).

Les applications Hibernate ne sont pas différentes des autres applications de base de données: l'ACIDité des transactions est gérée par la base de données, et non par Hibernate. Les entités, BTW, ne sont pas partagées. Chaque session Hibernate possède sa propre copie d'une entité donnée, qui contient les données telles qu'elles ont été lues dans la base de données de la transaction.

Lisez à propos des transactions de base de données et ACID. Que vous utilisiez Hibernate ou non ne change rien.

+0

Hibernate contient du cache de second niveau, donc lors de la validation des entités, celles-ci sont stockées dans le cache de second niveau, pas dans la base de données. Ai-je raison ? – friko

+0

Non. Les entités sont toujours sauvegardées dans la base de données. Ils peuvent également être stockés dans le cache de second niveau, mais le cache ne remplace pas la base de données. Et le cache de deuxième niveau est désactivé par défaut. Vous devez l'activer et choisir de mettre une entité en mémoire cache pour la stocker dans le cache de second niveau. Mon conseil: ne plaisante pas avec le cache de second niveau à moins d'avoir mesuré que c'était absolument nécessaire. Surtout si vous ne comprenez pas complètement comment Hibernate et les transactions fonctionnent sans ce cache. –

0

Les transactions sont des opérations atomiques dans DB (et Hibernate). Le moteur de base de données garantit que les utilisateurs ne recevront pas les entités à moitié mises à jour (si vous configurez le droit de gestion des transactions;)).

Si votre application dépend de l'intégrité des données, vous devez également implémenter une sorte de verrouillage des entités. Pour la plupart des cas d'utilisation, un verrouillage optimiste est suffisant. (Essayez googling pour ce terme, si ce n'est pas familier).

Questions connexes