Hibernate共享实体竞争条件

时间:2013-03-03 17:42:17

标签: java hibernate

我有一个问题,如果两个不同的网络用户在同一个实体上工作,会发生什么。 对于例如共享实体有四个字段:

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

现在,两个用户同时打开一个事务。其中一个是更新此实体,第二个用户正在读取此实体。以下步骤将更好地解释:

时间1:Hibernate实体存储在数据库中并具有值:a = b = c = d = 0且id = 1。
时间2:User1打开一个新的交易 时间3:User1读取HibernateSharedEntity,其中id = 1
时间4:User1正在修改所有字段:例如a = 2,b = 3,c = 4,d = 5 时间5:User1正在进行交易 时间6:Hibernate正在更新a = 2
时间7:Hibernate正在更新b = 3
时间8:现在User2打开一个新事务并读取该共享实体。题: 他找到了什么?他是否提供了一个半更新的实体,如: a = 2,b = 3,c = 0,d = 0?
时间9:Hibernate正在更新c = 4
时间10:Hibernate正在更新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}

现在User1想要更新这些实体,例如到这个状态:
entity1 = {a = 0,b = 0,c = 0,d = 0}
entity2 = {a = 0,b = 0,c = 0,d = 0}

。当User1正在进行更新事务时,User2想要获取这些共享实例和 我想避免,User2正在以这种状态重新处理这些实体:
entity1 = {a = 0,b = 0,c = 0,d = 0}
entity2 = {a = 5,b = 6,c = 7,d = 8}
如您所见,entity1已更新,但实体2未更新。这是我的应用程序中的关键点,并且不会出现这种情况。我怎么能避免这个? hibernate会照顾这个吗? 提前谢谢。

2 个答案:

答案 0 :(得分:1)

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

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

了解数据库事务和ACID是什么。无论你是否使用Hibernate都不会改变任何东西。

答案 1 :(得分:0)

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

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