Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Hibernate实体存储为HttpSession属性值_Java_Hibernate_Servlets_Lifecycle - Fatal编程技术网

Java Hibernate实体存储为HttpSession属性值

Java Hibernate实体存储为HttpSession属性值,java,hibernate,servlets,lifecycle,Java,Hibernate,Servlets,Lifecycle,我正在处理一个遗留Java应用程序,它的代码库很大,相当混乱。有一个相当标准的“User”对象存储在请求之间的HttpSession中,因此servlet在顶部执行类似的操作: HttpSession session = request.getSession(true); User user = (User)session.getAttribute("User"); 旧的用户身份验证层(我将不进行描述;只需说,它没有使用数据库)正在被用Hibernate映射到DB的代码所取代。所以“用户”现在

我正在处理一个遗留Java应用程序,它的代码库很大,相当混乱。有一个相当标准的“User”对象存储在请求之间的HttpSession中,因此servlet在顶部执行类似的操作:

HttpSession session = request.getSession(true);
User user = (User)session.getAttribute("User");
旧的用户身份验证层(我将不进行描述;只需说,它没有使用数据库)正在被用Hibernate映射到DB的代码所取代。所以“用户”现在是一个Hibernate实体

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

使用
session.merge(..)

(来自
会话
的文档):

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


只需确保

取决于用户是否在会话期间更改,或者您是否只想快速查找id、名称等。您始终可以合并()数据库中的用户,使其再次进入会话


您不需要每次都合并用户,因为这是一个数据库命中,您并不总是需要。但是使用merge,您可以将用户重新连接到当前会话。

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

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

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

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

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


非托管实体上的刷新是一个例外!他必须合并。@Aff:对。编辑后的文章反映了这一点