【发布时间】:2014-11-12 03:12:46
【问题描述】:
应用程序
具有 hibernate4 集成和 spring 安全性的 Spring-MVC 应用程序。 1 个控制器,两个视图,MySQL DB。
场景
一个 User 实体,其中包含一些类似于 User、roles 和 userPosts 之间关系的列表。
该应用程序有一个简单的控制器,集成了 Spring Security。
用户登录后,可以查看自己的帖子,或发布新帖子。
登录过程需要检索角色(延迟获取)和帖子(延迟获取)的数据库命中,数据已填满在用户实体实例中,然后通过控制器立即在模型中传递。
问题是:
在创建新的 Post JSP(简单形式)中,我正在访问 ModelAttribute (loggedUser) 以获取当前登录用户的实例,我认为,无需再次获取用户并建立所有存储库会话重新开始。但听起来没有办法这样做,因为我注意到存储的用户实体数据(我在登录后存储的)丢失了实体内的所有列表!在转发到视图时。这意味着任何新请求都需要再次填写 ModelAttribute。
我尝试过的事情:
我尝试启用 User 类型的类变量并将其设置为在 DB 上发生的操作,以存储检索到的数据,然后在 Model.addAttribute 中分配它,但没有运气,因为只有那些列表(List User.userRoles,List User.userPosts ) 一直被清空!
我尝试使用 ModelAndView.addObject 但又出现了一个新问题,它与将实体分配给字符串有关?!
我花了将近三天的时间来分析和弄清楚这些请求的处理机制 但听起来我必须始终保持访问数据库,因为我的实体的延迟加载列表总是被刷新!
我的问题是:
1 - 有没有办法保留从服务/存储库中检索到的实体数据,包括列表,同时将其填充到 ModelAttribute/model.addAttribute 中? (请注意,我不想包含用于取消延迟获取的过滤器)
2- 为什么使用 sessionAttribute 成功存储了 Entity 数据却丢失了那些延迟加载的项目?如果我们假设当调用新的控制器方法时会话被清除时会清除列表。
3- 是否有任何建议的方案来节省性能,或最大限度地减少从数据库中获取数据的命中?我是否缺少一些关键的设计/逻辑良好实践?
感谢您的宝贵时间。
更新
好的,谢谢jmvivo和M。 Deinum 为您解答。我可以解决这个问题,现在一旦从数据库中获取数据,我就可以共享它,而无需在重定向/新控制器调用时再次点击数据库。
解决方案:
使用 Map 模型存储登录的用户,并将其传递到不同的页面。
观察和注意事项:
使用实体、服务和存储库创建的对象都类似于一个数据模型,一旦调用方法的范围完成,就必须临时持久化并清除所有使用的资源。这就是用户实体在转发到其他控制器或其他方法后清除某些数据部分的原因。
换句话说,我只需要创建一个用户类,或者一些对象来获取 jpa 检索到的数据的副本,这样 dao 对象在 DAO 被清除后不会影响我读取的数据。
没有分离 DAO 层和实现层的概念,我认为通过这个小练习,我第一次从理论中很好地理解了它。 另一个观察结果是,由于我可以重定向到一个 jsp 页面,我还可以调用映射控制器方法,将任何结果传递给它,而无需使用 Spring 的调度程序来执行此操作(这只是为了节省不必要的重新映射处理):
@requestMapping("/home")
public String home(Map..){
// if authorised
//get user from map no need to call service to fill user based on principal name
SomeUserClass user = map.get("userfromDB") // user will be here :)
//.. some logic
return "home-page";
}
@requestMapping("/post")
public String createUserPost(Map.. map, Model model, Principal p){
// access DB here and store result into map
SomeUserClass user = service.prepareAUserWithUserName(p.getName());
// save user copy in map, after the scope ends or another controller method happens the user will lose all lazily loaded data, but the map will be maintained by the chain.
map.put("userfromDB", user);
// if I want to redirect to home I can:
// call 1-home(Map)
// or 2- return the result of home function after setting model again
// or simply return the page without the need for extra processing as result would be the same
// return "home-page"
//.. some logic
return "home-page";
}
这对我的应用程序的性能产生了很大影响。 我希望这会对某人有所帮助。
【问题讨论】:
标签: hibernate jsp spring-mvc jpa database-performance