java – Hibernate实体存储为HttpSession属性值

我正在处理一个带有大量相当混乱的代码库的遗留
Java应用程序.有一个相当标准的’User’对象在请求之间存储在HttpSession中,所以servlet在顶部做这样的事情:

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

旧的用户身份验证层(我将不会描述;足以说,它没有使用数据库)正被替换为使用Hibernate映射到DB的代码.所以’User’现在是一个Hibernate实体.

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

最佳答案 假设您正在为每个请求 – 响应周期创建一个新的hibernate会话,可以将一个分离的对象合并到新的hibernate会话中,但我会完全避免这种方法.

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

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

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

我强烈建议您阅读以下内容,特别是有关长会话和分离对象的部分:

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

点赞