2010-05-29 76 views
3

我处理的大,相当繁琐的代码库遗留的Java应用程序。还有那个被存储在请求之间HttpSession中一个相当标准的“用户”的对象,所以servlet的顶部做的东西是这样的:Hibernate的实体属性值

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

老用户认证层(这我就不一一介绍了,足以比如说,它没有使用数据库)正在被替换为使用Hibernate映射到数据库的代码。所以'用户'现在是一个Hibernate实体。

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

回答

1

假设你为每个请求 - 响应周期创建一个新的Hibernate Session,有可能分离对象合并到新的Hibernate Session,但我会完全避免使用此方法。

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

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

通过尝试将HttpSession中的用户对象合并到您的hibernate会话中,您基本上正在尝试直接操作hibernate的IdentityMap,将任何hibernate“认为”应该与其他事物相关联,并且可以理解这会导致问题。正如我所说,虽然可以将分离的对象附加到休眠会话中,但我会避免它。祝你好运,你采取任何方式。

我会强烈建议阅读以下内容,你的情况特别是部分在长对话和分离对象:对非托管实体

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

0

取决于如果会话期间用户改变,或者如果你只是想ID,名称等进行快速查找。您始终可以将数据库中的用户合并()以将其重新放入会话中。

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

+1

刷新是个例外!他必须合并。 – Affe 2010-05-29 21:11:02

+0

@Affe:正确。编辑帖子反映了这一点 – Daniel 2010-05-30 17:36:27

相关问题