我们需要将hibernate会话设置为线程本地对象

时间:2013-07-24 10:36:53

标签: java hibernate

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

获取会话,

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

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

2 个答案:

答案 0 :(得分:1)

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

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

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

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

一致性问题有点棘手,没有一个适合所有model。你需要做的是考虑你需要什么级别的一致性 - 如果数据在被写入的同时被读取,那么这些问题是否重要,更新绝对必须是原子的等等。

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

使用数据库,您需要查看database level locks,并通过应用适当的isolation levels创建适合您应用的方案。

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

答案 1 :(得分:0)

我不确定你是否强迫使用ThreadLocal。使用ThreadLocal存储会话对象肯定不是一个好主意,特别是当你使用hibernate和spring时。

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

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

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

    Session session = sessionFactory.getCurrentSession();

  3. 以下是related article的链接。

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