我有一个以下映射,它检索一些“场景”细节并在jsp页面中显示它。
@RequestMapping(value="/{id}",method = RequestMethod.GET)
public ModelAndView showScene(@PathVariable String id){
ModelAndView mv = new ModelAndView("/Scene/scene");
//retrieving Scene using Hibernate
Scene scene = service.getScene(Long.parseLong(id));
mv.addObject("name", scene.getName());
mv.addObject("desc", scene.getDescription());
//etc....
return mv;
}
我的问题是,scene对象中的一个字段是png图像为byte [],我需要显示它。我知道我可以创建另一个控制器来处理所有.png扩展请求并返回byte []。类似的东西:
<servlet-mapping>
<servlet-name>PNGHandler</servlet-name>
<url-pattern>*.png</url-pattern>
</servlet-mapping>
并将对图像的引用发送为:
mv.add("image", "image/"+scene.getId()+".png");
但是我需要在png控制器中再次检索byte [],这将花费额外的Hibernate Transaction。有什么工作可以保存这个事务而不是两次检索byte []吗?
提前谢谢。
答案 0 :(得分:2)
最简单的解决方案是第一个请求在会话中存储byte[]
(或整个Scene
对象),第二个请求是从会话中获取它并将其流回客户端。您可以在固定密钥下将数据存储在会话中,或者您可以每次生成一个新密钥,将其存储在该密钥下的会话中,然后在呈现时将密钥编码为<img>
URL页。
您必须注意不要在会话中放置太多图像,因此您可以在检索后删除它们,或者一次只允许会话中的一个。
答案 1 :(得分:1)
我相信春天的方式是使用两个控制器方法,一个包含像你一样的页面,第二个只返回图像。
如果你害怕性能,你可以使用hibernate属性lazyloading为你的字节数组。因此,当您仅使用名称和其他内容(数组除外)时,将不会加载数组。
但据我所知,属性延迟加载需要某种字节码增强。因此,如果这是一个巨大的问题,您可以考虑直接使用查询加载属性,而不是通过映射类加载它。
答案 2 :(得分:1)
我会说 - 将字节分隔给不同的Hibernate映射实体(可能是Image?),并让Scene通过延迟加载的关系引用它。
然后,只有在您真正需要时才能加载图像。如前所述,执行showScene的Controller不需要加载图像,它们可以由不同的Controller处理。
这样做的好处是: