【问题标题】:Hibernate entities stored as HttpSession attribute values存储为 HttpSession 属性值的休眠实体
【发布时间】:2010-05-29 18:28:19
【问题描述】:

我正在处理一个遗留 Java 应用程序,其中包含一个庞大且相当混乱的代码库。有一个相当标准的“用户”对象存储在请求之间的 HttpSession 中,因此 servlet 在顶部执行以下操作:

HttpSession session = request.getSession(true);
User user = (User)session.getAttribute("User");

旧的用户身份验证层(我不会描述;我只想说,它没有使用数据库)正在替换为通过 Hibernate 映射到数据库的代码。所以“用户”现在是一个 Hibernate 实体。

我对 Hibernate 对象生命周期的理解有点模糊,但现在将 'User' 存储在 HttpSession 中似乎成为一个问题,因为它将在下一次请求期间在不同的事务中检索。在这里做什么是正确的?下次我可以使用 Hibernate Session 对象的 update() 方法重新附加 User 实例吗?我需要吗?

【问题讨论】:

    标签: java hibernate servlets lifecycle


    【解决方案1】:

    假设您为每个请求-响应周期创建一个新的休眠会话,可以将分离的对象合并到新的休眠会话中,但我会完全避免这种方法。

    尝试在 HttpSession 上存储一个密钥,该密钥可用于通过休眠为每个传入请求查找用户。如果您担心访问数据库以检索可以存储在 HttpSession 中的内容的性能后果,请不要担心 - 您始终可以使用 hibernate 支持的缓存框架来减少数据库访问次数。另一种提高性能的方法是使用乐观锁定。

    虽然我没有查看过hibernate 的源代码,但我认为hibernate 使用了“身份映射”模式。这是一个 Map,它使用实体的 id 作为 Map 中的键,并将关联的实体对象作为 Map 中的值。每当从休眠会话中检索实体时,休眠将查看会话的身份映射以查看它是否存在。如果它在那里,它将从地图中返回实体。如果它不存在,它将从数据库中检索实体并将其放在地图上,然后返回实体。这意味着对于给定休眠会话使用相同键(即 id、userId 等)访问给定用户的连续查询将收到对相同用户对象的引用,因此每个查询将能够“看到”对另一个查询的用户对象。出于这个原因,为每个传入请求创建一个新的休眠会话是绝对必要的,这样给定用户的并发请求就不必将它们各自的线程锁定在它们的公共用户对象上。不同的休眠会话将各自拥有自己的身份映射,因此不会返回对同一用户对象的引用。

    通过尝试将 HttpSession 中的 User 对象合并到您的休眠会话中,您基本上是在尝试直接操作休眠的 IdentityMap,用其他东西替换休眠“认为”应该存在的任何东西,并且可以理解这可能会导致问题。正如我所说,虽然可以将分离的对象附加回休眠会话,但我会避免它。不管你采取什么方法,祝你好运。

    我强烈建议您阅读以下内容,尤其是关于长时间对话和分离对象的部分:

    http://docs.jboss.org/hibernate/core/3.3/reference/en/html/transactions.html

    【讨论】:

      【解决方案2】:

      取决于用户是否在会话期间发生更改,或者您是否只需要 id、名称等进行快速查找。您可以随时 merge() 数据库中的用户以使其再次进入会话。

      您不需要每次都合并用户,因为它是您并不总是需要的数据库命中。但是通过合并,您可以将用户重新附加到当前会话。

      【讨论】:

      • 在非托管实体上刷新是个例外!他必须合并。
      • @Affe:正确。编辑帖子以反映这一点
      【解决方案3】:

      使用session.merge(..)

      (来自Session 的文档):

      也可以通过调用 merge() 将瞬态或分离实例的状态作为新的持久实例持久化。

      一定要override hashCode() and equals() properly.

      【讨论】:

        猜你喜欢
        • 2012-09-09
        • 2012-01-21
        • 2023-03-17
        • 2012-01-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-06-23
        • 1970-01-01
        相关资源
        最近更新 更多