【问题标题】:Sharing session entities共享会话实体
【发布时间】:2013-03-05 10:22:55
【问题描述】:

假设我们有一个使用 Hibernate 的 Web 应用程序。 我的问题是,如果来自不同用户的两个不同交易访问和操作同一个实体,会发生什么?例如,我们有一个名为“Student”的实体,它有一个字段“age”。现在,来自不同用户的两个不同事务,使用 Hibernate 会话获取该实体,例如:

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

然后一位用户操作年龄字段,例如: 学生.setAge(12); 第二个用户是否完全在另一笔交易中看到了这种变化? 我的意思是如果第二个用户在他自己的事务中调用 学生.getAge(), 他看到新值 - 12 了吗? 请注意,更改年龄属性的第一个用户尚未提交事务。

【问题讨论】:

  • 提供完整的程序以获得清晰的想法。一般在一个web应用中,两个不同的事务会使用Student实体的两个不同的对象。

标签: java hibernate web


【解决方案1】:

这只是部分休眠问题。其他用户是否看到未提交的数据取决于您是否已将数据库连接的隔离级别更改为未提交读。您想要这样做的正当理由并不多,除非被覆盖,否则休眠会将其默认为已提交读。所以一般来说,不,其他用户在事务提交之前不会看到更改。

如果您降低了隔离级别,那么它归结为 SQL 实际发送到数据库的时间。这是基于休眠的刷新设置,在多层系统中可能有点难以预测。但是基本上调用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

【讨论】:

  • 感谢 Affe 的详细解答。这就是我想读的。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    在这种情况下,Hibernate 擅长在多个线程中同时更新。

    首先,在这种情况下不存在线程安全问题。因为每个事务都有自己的会话,每个会话将分别将其加载的对象保存在其所谓的一级缓存中。两个线程中的两个实例不会互相看到,

    其次,当多个事务更新同一记录时,优化锁定机制将起作用。这是先到先得的模式。第一个提交的事务 secceeds,第二个提交的事务将失败并抛出异常。因为 hibernate 会在更新操作提交之前检查 versin 属性以查看版本是否为原始版本。

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

    【讨论】:

      猜你喜欢
      • 2017-04-06
      • 2012-08-24
      • 2011-09-12
      • 2016-06-05
      • 2015-08-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-01
      相关资源
      最近更新 更多