我需要知道,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,这是正确的。
但是当我尝试在线程环境中运行相同的代码时,它会产生错误的结果。
答案 0 :(得分:20)
实现者不应该是线程安全的。相反,每个线程/事务应该从SessionFactory获取自己的实例。
即使考虑到这一点,您的行为可能仍然不是您所期望的,因为交易发挥作用。您必须设置正确的transaction isolation level。请参阅configuration guide,hibernate.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中以两种方式创建会话。
是。它提供了线程安全性,因为它确保如果会话不存在,它将为每个线程创建一个会话。交易和自动会话结束附于此。
这不是线程安全的。开发人员手动需要管理事务和会话刷新和关闭操作。
答案 4 :(得分:0)
Session对象被设计为由单个线程使用。在内部,Session使用许多非线程安全的数据结构,因此无法使其成为线程安全的。
更多,您甚至不需要使用线程安全的会话。如果您的用例是共享缓存的实体,则应该使用第二级缓存,它是线程安全的,可以在群集环境中使用。
话虽这么说,需要一个线程安全的Session是一种代码味道,表明数据访问层的设计存在缺陷。