2013-03-01 150 views
1

假设我们有一个使用Hibernate的Web应用程序。 我的问题是关于发生什么,如果来自不同用户的两个不同转换访问和操作同一个实体?例如,我们有一个名为“学生”的实体,它有一个“年龄”字段。共享会话实体

Student student = session.load(1); // 1 is the id of some student 

,然后一个用户操纵年龄字段e.g::现在,来自不同用户的两个不同的交易,使用Hibernate会话e.g获取该实体 student.setAge(12); 第二位用户是否看到完全另一个事务中的更改? 我的意思是如果第二个用户在他自己的交易中调用 student.getAge(), 他是否看到新的值 - 12? 请注意,更改age属性的第一个用户尚未提交交易。

+0

提供完整的程序来获得清晰的概念。通常在Web应用程序中,两个不同的事务将使用“学生”实体的两个不同对象。 – 2013-03-01 20:44:33

回答

1

这只是部分的冬眠问题。其他用户是否看到未提交的数据取决于您是否已将数据库连接的隔离级别更改为读取未提交。有没有太多有用的理由你会这样做,休眠会默认它读取提交,除非被覆盖。所以通常情况下,其他用户在事务提交之前不会看到更改。

如果您已经降低了隔离级别,那么最终归结为SQL实际发送到数据库的时间。这是基于休眠的flush设置,可能在多层系统中难以预测。但基本上调用setAge不会将SQL发送到其他人可以看到的数据库。导致刷新的东西必须发生,那些东西是依赖于配置的。

此外请注意,如果第二个会话在提交更新之前加载实体,即使第一个会话提交更新,第二个会话也不会自动奇迹般地更新其内存实体,除非您明确地调用它的刷新。例如,

Time 1: Session A loads Student 1 
Time 2: Session B loads Student 1 
Time 3: Session A sets new age and commits 
Time 4: Session B gets Age, will still see old value 
Time 5: Session B calls refresh on Student 1 
Time 6: Session B gets Age, will see new value set in Session A 
+0

谢谢感谢您的详细解答。这是我想读的。 – friko 2013-03-01 20:53:01

+0

我明白了,再次感谢。 – friko 2013-03-01 21:02:05

0

请看这里:Hibernate session thread safety。我认为这与你所要求的非常相似。基本上,在多个线程中使用会话并不是一个好主意。因此,假设您正在使用不同的会话,第二个用户将看不到更改。

+0

感谢您的快速回复。 – friko 2013-03-01 21:16:24

0

Hibernate擅长在多线程中并发更新,就像这种情况一样。

首先,在这种情况下不存在线程安全问题。由于每个事务都拥有自己的会话,因此每个会话都将其加载的对象分别保存在其所谓的第一级缓存中。在两个线程中的两个实例将不会看到对方,其次,当多个事务更新同一记录时,optimastic锁定机制将工作。它是先到先得的模式。第一个提交的事务将会停止,第二个提交的事务将失败并抛出异常。因为hibernate会在其更新操作提交之前检查versin属性以查看版本是否为原始版本。

看到http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/transactions.html