2013-03-03 83 views
0

我有一个问题会发生什么,如果两个不同的Web用户在同一个实体上工作。 例如共享实体有四个字段:休眠共享实体竞争条件

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

现在,两个用户都在同一时间打开一个事务。其中之一是更新这个实体,第二个用户正在阅读这个实体。下面的步骤将解释它好得多:

时间1:休眠实体被存储在数据库中,并且具有值:A = B = C = d = 0,ID = 1。
时间2:用户1打开新的事务。
时间3:用户1读取HibernateSharedEntity其中id = 1周
时间4:用户1正在修改所有字段:例如a = 2,b = 3,c = 4,d = 5。
时间5:用户1正在提交事务。
时间6:休眠正在更新a = 2
时间7:休眠正在更新b = 3
时间8:现在用户2打开一个新事务并读取该共享实体。问题: 他检索了什么?他是否接受了一个半更新的实体: a = 2,b = 3,c = 0,d = 0?
时间9:休眠正在更新C = 4
时间10:休眠正在更新d = 5

我想避免半更新实例。这是我的应用程序的关键点。 如果第二用户希望检索该共用实体,我想的是,第二 用户只能处于两种状态,在A = B = C = d = 0的状态(以前提交)或 a = 2的读此共享实体,b = 3,c = 4,d = 5状态(提交后)。我知道hibernate可以使一个插入来更新所有这些值,但在我的应用程序中它似乎更复杂,因为这个共享实体与其他共享实体有关系,也可以由User1更新。所以从现在开始,hibernate不能让一个插入来更新这两个共享实体。因此,当User1在一个事务中更新更多的共享实体时,是否有这种可能性,User2可以以“非同步状态”读取这些实体。我的意思是当一个实体更新时,但另一个实体没有更新?

我认为它可以复杂,所以我会尝试更多的解释: 在我的应用程序共享实体进行同步。例如。有两个共享实体,如:
entity1 = {a = 1,b = 2,c = 3,d = 4}
entity2 = {a = 5,b = 6,c = 7,d = 8}

现在用户1想要更新这些实体,例如到这种状态:
使用实体= {A = 0,B = 0,C = 0,d = 0}
ENTITY2 = {A = 0,B = 0,C = 0,d = 0}

。而用户1正在更新事务,用户2希望读取这些共享实例和 我想避免,即用户2被readeing在这样的状态下这些实体:
使用实体= {A = 0,B = 0,C = 0,d = 0}
ENTITY2 = {A = 5,b = 6,C = 7,d = 8}
正如你可以看到,使用实体被更新,但ENTITY2不是。这是我申请中的关键点,并不存在这样的情况。我怎样才能避免这种情况?冬眠是否照顾这个? 预先感谢您。

回答

1

您的第一个场景是不可能的。 Hibernate在事务提交之前将更改写入数据库,而不是之后。用户2将读取已提交给数据库的内容,因为它在第一个事务提交后读取实体。如果用户2在提交第一个事务之前从数据库中读取数据,它将读取第一个事务开始之前的状态(只要数据库隔离级别是默认的READ_COMMITTED)即可。

Hibernate应用程序与其他数据库应用程序没有区别:事务的ACIDity由数据库处理,而不是由Hibernate处理。实体,顺便说一句,不共享。每个Hibernate会话都有自己的给定实体副本,其中包含从事务中的数据库中读取的数据。

阅读有关数据库事务和ACID的信息。不管你是否使用Hibernate都不会改变任何东西。

+0

Hibernate确实包含二级缓存,所以在提交实体时,这些存储在二级缓存中,而不是数据库中。我对吗 ? – friko 2013-03-03 22:10:50

+0

编号实体始终保存在数据库中。它们也可能存储在二级缓存中,但缓存不会替换数据库。而二级缓存默认是禁用的。您必须启用它,并选择使实体可缓存,才能将其存储在二级缓存中。我的建议是:除非您已经测量过它是绝对必要的,否则不要混淆二级缓存。特别是如果你没有完全理解Hibernate和事务如何在没有这个缓存的情况下工作。 – 2013-03-03 22:13:26

0

事务是DB(和hibernate)中的原子操作。数据库引擎保证用户不会得到一半更新的实体(如果您配置事务管理权限;))。

如果您的应用程序依赖于数据完整性,则还应该实施某种实体锁定。对于大多数用例而言,乐观锁定就足够了。 (如果不熟悉,请尝试使用Google搜索这一术语)。