Hibernate会话线程安全吗?

时间:2010-09-23 11:24:08

标签: java hibernate session thread-safety hibernate-session

我需要知道,Hibernate的会话是否是线程安全的。但很明显,每个线程都会附加一个新会话来执行。但我的问题是,如果在一个线程中我更新了一个实体的某个值,那么这会在同一时间执行中反映在其他线程中吗?

我的问题是当我从两个线程顺序触发更新时,值会正确更新,但是当我几乎完全触发更新时它会失败。

例如。 现阶段的表。

  ID      NAME      MARKS
------- --------- --------
  1       John       54

我正在尝试做以下事项:

Student student = session.load(Student.class, 1);
student.setMarks(student.getMarks() + 1);
session.update(student);
session.close();

当我尝试在循环中运行上面的代码10时,表“student”中的“marks”值被正确更新,即值更新为64,这是正确的。

但是当我尝试在线程环境中运行相同的代码时,它会产生错误的结果。

5 个答案:

答案 0 :(得分:20)

  

实现者不应该是线程安全的。相反,每个线程/事务应该从SessionFactory获取自己的实例。

即使考虑到这一点,您的行为可能仍然不是您所期望的,因为交易发挥作用。您必须设置正确的transaction isolation level。请参阅configuration guidehibernate.connection.isolation媒体资源。

答案 1 :(得分:17)

Hibernate会话和线程不混合。

您不应该同时使用多个线程的会话,我建议您仅使用单个线程中的会话。数据库会话实现甚至不需要是theadsafe。

当您开始在多个线程中执行操作时,您还必须考虑事务会发生什么。事务与当前线程相关联。这变得很快,你进入实施者没有测试过产品的区域。

到最后,生命太短暂,不能迷失在沼泽中。

答案 2 :(得分:4)

Hibernate会话不是线程安全的。使用TheadLocal类为每个线程创建会话: -

 private static ThreadLocal<Session> threadSafeSession = new ThreadLocal<Session>() {
    protected Session initialValue(){
    return sf.openSession();
      }
    };

在你的方法中,每个线程的get会话为: -

Session session = threadSafeSession.get();

答案 3 :(得分:2)

这取决于您创建会话的方式。

可以在hibernate中以两种方式创建会话。

  1. 的getCurrentSession()
  2.   

    是。它提供了线程安全性,因为它确保如果会话不存在,它将为每个线程创建一个会话。交易和自动会话结束附于此。

    1. 的openSession()
    2.   

      这不是线程安全的。开发人员手动需要管理事务和会话刷新和关闭操作。

答案 4 :(得分:0)

  

Session对象被设计为由单个线程使用。在内部,Session使用许多非线程安全的数据结构,因此无法使其成为线程安全的。

     

更多,您甚至不需要使用线程安全的会话。如果您的用例是共享缓存的实体,则应该使用第二级缓存,它是线程安全的,可以在群集环境中使用。

     

话虽这么说,需要一个线程安全的Session是一种代码味道,表明数据访问层的设计存在缺陷。