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

获取会话,

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

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

4

2 回答 2

3

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

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

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

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

一致性问题有点棘手,没有一种尺寸适合所有模型。您需要做的是考虑您需要什么级别的一致性 - 诸如在写入数据的同时读取数据是否重要,更新是否绝对必须是原子的等问题。

一旦你知道了这些问题的答案,你就需要在两个地方查看一致性——在数据库和代码中。

对于数据库,您需要查看数据库级别的锁,并通过应用适当的隔离级别来创建适合您的应用程序的方案。

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

于 2013-07-24T11:39:13.607 回答
2

我不确定您是否有使用ThreadLocal. 使用ThreadLocal存储会话对象绝对不是一个好主意,特别是当您使用 hibernate 和 spring 时。

在 Spring 中使用 Hibernate 的典型方案是:

  1. sessionFactory在你的 DAO 中注入。我假设您sessionFactory已经配置了由池数据源支持的。

  2. 现在在您的 DAO 类中,可以按如下方式访问会话。

    Session session = sessionFactory.getCurrentSession();

这是相关文章的链接。

请注意,此示例特定于 Hiberante 3.x API。这在内部处理了会话创建/关闭/线程安全方面,并且也很整洁。

于 2013-07-24T13:19:27.317 回答