java - 我们需要将 hibernate session 设置为线程本地对象

标签 java hibernate

ThreadLocal<Session> tl = new ThreadLocal<Session>();
    tl.set(session);

获取 session ,

  Employee emp = (Employee)((Session)tl.get().get(Employee.class, 1));

如果我们的应用程序是基于 Web 的,则 Web 容器会为每个请求创建一个单独的线程。 如果所有这些请求同时使用同一个 Session 对象,我们应该得到 我们的数据库操作中出现不需要的结果。 为了克服上述结果,最好将 session 设置为 threadLocal 对象 它不允许并发使用 session 。我认为,如果它是正确的,那么应用程序性能应该非常差。 在上述场景中什么是好方法? 如果我走错了路,在什么情况下我们需要使用 ThreadLocal。 我是 hibernate 新手,如果这种类型的问题很愚蠢,请原谅。 提前致谢。

最佳答案

将 Hibernate Session 放在 ThreadLocal 中不太可能实现您想要的请求之间的隔离。当然,您使用由 DataSource 的连接池实现支持的 SessionFactory 为每个请求创建一个新的 Session,这意味着对Session 无论如何都在堆栈上。恕我直言,更改对成员变量的本地引用只会使代码复杂化。

无论如何,确保单个容器内的隔离并不能解决实际问题 - 如何在多线程环境中保持一致性的同时高效访问数据。

您提到的问题有两个部分 - 第一个部分是数据库连接是一种昂贵的资源,第二个部分是您需要确保线程/请求之间某种程度的数据一致性。

解决资源问题的一般方法是使用数据库连接池(我猜您已经在这样做了)。处理每个请求时,都会从池中获取连接并在完成后返回,但重要的是,池中的连接在请求的生命周期之外仍会得到维护,从而避免了每次需要时创建连接的成本。

一致性问题有点棘手,没有一种方法可以放之四海 model 。您需要做的是考虑您需要什么级别的一致性 - 诸如数据在写入的同时读取是否重要、更新是否绝对必须是原子的等问题。

一旦您知道了这些问题的答案,您就需要在两个地方考虑​​一致性 - 数据库和代码。

有了数据库你需要看看database level locks并通过应用适当的 isolation levels 创建适合您的应用程序的方案.

有了代码,事情就有点复杂了。在更新写回之前,数据通常会加载并显示一段时间 - 如果有单个用户,这没有问题,但在多用户系统中,可能会根据陈旧数据进行更新或同时发生多个更新。采用最后更新获胜的策略可能是可以接受的,在这种情况下很简单,但如果不是,您将需要使用版本号或新旧比较来确保应用更新时的完整性。

关于java - 我们需要将 hibernate session 设置为线程本地对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17831566/

相关文章:

java - 当两个单独的模式具有相同的命名空间时,如何告诉 JAXB 在单独的包中生成类?

java - 如何从 Jmeter 中的输入数据中删除 Extra(")

sql - 让 Hibernate 绑定(bind)参数类型 "char(1)"而不是 "nvarchar(4000)"?

java - 事务提交后 Hibernate 线程未完成

PreAuthorize 注释中的 Java 8/Spring 常量

Java 7 中的 Java SNIServerName 支持

java - CrudRepository.save(Iterable<S>) 是原子的吗?

hibernate - 重复结果休息服务 Spring boot

java - 继承: Annotate @Id of Super class to child class having different sequences

java - 如何将数组列表传递给 Controller