我正在处理一个遗留的 Java 应用程序,它有一个庞大且相当混乱的代码库。有一个相当标准的“用户”对象,在请求之间存储在 HttpSession 中,因此 servlet 在顶部执行类似的操作:
HttpSession session = request.getSession(true);
User user = (User)session.getAttribute("User");
旧的用户身份验证层(我不会描述;只需说,它没有使用数据库)正在被使用 Hibernate 映射到数据库的代码所取代。所以“用户”现在是一个 Hibernate 实体。
我对 Hibernate 对象生命周期的理解有点模糊,但似乎在 HttpSession 中存储“User”现在成为一个问题,因为它将在下一个请求期间在不同的事务中检索。在这里做什么是正确的?我可以在下次使用 Hibernate Session 对象的 update() 方法重新附加 User 实例吗?我需要吗?
假设您正在为每个请求-响应周期创建一个新的休眠会话,则可以将分离的对象合并到新的休眠会话中,但我会完全避免这种方法。
相反,尝试在 HttpSession 上存储一个密钥,该密钥可用于通过 hibernate 查找每个传入请求的用户。如果您担心访问数据库以检索可存储在 HttpSession 中的内容的性能后果,请不要担心 - 您始终可以使用 hibernate 支持的缓存框架来减少数据库访问次数。提高性能的另一种方法是使用乐观锁定。
虽然我没有看过 hibernate 源代码,但我认为 hibernate 使用“身份映射”模式。这是一个Map,它使用实体的id作为Map中的键,并将关联的实体对象作为Map中的值。每当从 hibernate 会话中检索实体时,hibernate 都会查看会话的身份映射以查看它是否存在。如果存在,它将返回地图中的实体。如果不存在,它将从数据库中检索实体并将其放在地图上,然后返回该实体。这意味着对于给定的 hibernate 会话,使用相同键(即 id、userId 等)访问给定 User 的连续查询将收到对同一 User 对象的引用,因此每个查询将能够“查看”对其他查询的 User 对象。因此,绝对有必要为每个传入请求创建一个新的休眠会话,以便给定用户的并发请求不必将其各自的线程锁定在其公共用户对象上。不同的 hibernate 会话都有自己的身份映射,因此不会返回对同一 User 对象的引用。
通过尝试将 HttpSession 中的 User 对象合并到 hibernate 会话中,您基本上是在尝试直接操作 hibernate 的 IdentityMap,用其他东西替换 hibernate“认为”应该存在的任何内容,可以理解,这可能会导致问题。正如我所说,尽管可以将分离的对象附加回休眠会话,但我会避免这样做。无论您采取什么方法,祝您好运。
我强烈建议您阅读以下内容,特别是有关长时间对话和独立对象的部分:
http://docs.jboss.org/hibernate/core/3.3/reference/en/html/transactions.html http://docs.jboss.org/hibernate/core/3.3/reference/en/html/transactions.html
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)