【发布时间】:2019-03-19 05:31:43
【问题描述】:
我有一个基于 Spring MVC 和 Hibernate 的小型 Web 应用程序。我的 User 对象与 Pet 对象具有 oneToMany 关系:
@OneToMany(mappedBy="user", cascade=CascadeType.ALL, fetch=FetchType.EAGER)
private Set<Pet> myPets;
即使我在登录后将我的用户对象保留在 Session 中(我知道这是一种罪过),并且它包含了他的 Pets,每次调用 Controller 方法时,在它返回一个 ModelAndView 对象后,日志显示休眠触发选择。
例如
@RequestMapping(value = "/in_pet-see", method = RequestMethod.GET)
public ModelAndView getSee(@RequestParam("pid") Integer pId, ModelAndView model) {
User u = getUserFromSession();
if(u==null) {
u = getUser();
}
Set<Pet> pets = u.getMyPets();
Pet p = getPetFromSet(pets, pId);
model.addObject("user", u);
model.addObject("petType", petTypeMap.get(p.getType()));
model.addObject("petAttribute", p);
model.setViewName("b-see-pet");
return model;
}
private User getUserFromSession() {
return (User)session().getAttribute("user");
}
public static HttpSession session() {
ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
return attr.getRequest().getSession(true); // true == allow create
}
private Pet getPetFromSet(Set<Pet> set, int pId) {
Pet myPet = null;
for (Iterator<Pet> it = set.iterator(); it.hasNext(); ) {
Pet p = it.next();
if (p.getPetId()==pId) {
myPet = p;
}
System.out.println("Pet found");
}
return myPet;
}
我怎样才能避免这种情况?
注意
我解决这个问题的方法是克隆休眠对象并将克隆放在 HttpSession 中,然后在那些可以对用户或用户的依赖对象进行更改(在我的应用程序中很少见)的方法中,在这些方法的末尾调用同步方法:
/** Get a new user from DDBB, after some change and put it on Session to deliver fresh data */
private void sinchronizeUser() {
User oldSmith = getUserFromSession();
User u = myUserService.loadUserById(oldSmith.getUserId());
User smith = (User) u.clone();
session().setAttribute("user", smith);
}
【问题讨论】:
-
如果没有完整的控制器和流程,这是无法回答的。您还没有包含
getPetFromSet。如果您有@ModelAttribute带注释的方法等,它也不可见。也不要使用该构造来获取HttpSession而只是将其作为HttpSession类型的方法参数注入。 -
嗨,getPetFromSet 应该不重要。它只是集合内的一个迭代,寻找一个特定的 id
-
您还没有添加完整的控制器,也没有解释发出了哪个选择语句。同样显然,如果没有用户,您可以执行其他操作来获取用户,这也让我想知道您如何将用户存储在会话中。总而言之,这里的图片不完整,无法回答您的问题。
-
嗨,Deinum,谢谢,我的控制器很长,所有重要的东西都在这里。我终于找到了一种防止 Hibernate 选择的方法,它只是克隆 Hibernate 对象并在我的 HttpSession 中使用克隆对象。问候,
-
这不是解决方案,而是破解/解决方法。
HttpSession中的User不再附加到休眠状态,除非您将其存储在会话中的每个请求中,这基本上违背了将其存储在会话中的目的。
标签: spring hibernate session model-view-controller