关于open session in view,想在此请教!

最近公司开始了个新项目,使用的框架是Struts2+Spring2+Hibernate3,当然在这此我们不讨论架构。
主要是想讨论一下关于hibernate提到的open session in view.在我们的项目中,我们的事务边界是定界在service层。我们用hibernate的惰性加载,假设检索出一个对象A,这个对象又关联到另一对象B,那么我们检索完成对后就关闭了session,这时的B对象只是一个代理,并不是实际对象。那么当我们在界面上想通过检索出来的A对象再看B对象的属性的话,是不是要再重开一个session,把A对象再放到另一个session中去呢?这样如果应用open session in view,就不会出现这种脱管对象了,是吧,但这样的话,这个session不是要一直开着吗?这样对性能是一种考验吧。还有另一种做法是,检索出来A对象的时候通过copyproperties()拷贝出另一个对象出来,这样拷贝时就会把B对象的实际对象也检索出来关联到新的对象中去吧?但是这样也有问题:如果A对象里有n个类似于B对象的对象时又或者B对象还又关联到其他对象时,这个拷贝出来的对象不是会越来越大?这也是个问题,是吧?不知道各们对我的问题是不是认同,如果认同有什么解决方案?谢谢!

>这样如果应用open session in view,就不会出现这种脱管对象了,是吧
不是,Open Session 其实是Open request,这个Session是存在一个request到response周期中。

谢谢banq老师的的回复,我现在明白您说的open session 就是open request,这边的session是hibernate的session而非httpsession,对吧?也就是说客户一次点击--一般一个请求都是以一次点击表现吧,这样就在service调用dao了,这时session打开了,当用户得到自己想要的结果时,就是response的结束了,这时session也结束了,是吧?那么用户检索到的对旬还是一个脱管对象,是这样吗?当他访问这个脱管对象的关联对象的话,有两种可能:一种是再去开启另一个session,把这个脱管对象再放到新的session中去;还有就是出现异常,这代表这个脱管对象关联的对象实际是一个代理对象,是吧?

> >这样如果应用open session in view,就不会出现这种脱管对象了,是吧
>不是,Open Session 其实是Open request,这个Session是存在一个request到response周期中。
我怎么觉得楼主说的是对的,open session in view其实就是延长了session的生命周期,性能肯定会受到影响,如果页面渲染耗费时间较长的话,说不定还会出现连接耗尽的情况。

楼上的朋友,我想首先我说得还不够细吧,你的理解也是没错的。我想Open session in view这种模式,看你把事务边界设在哪了,如果是通过spring拦截器的话,那就像你说的会延长了session的生命周期,导致性能问题!我们的项目是定界于service层,而其实service的动作也是受web控制层的调遣,是吧?当用户发送一个请求过来时,web控制层通过了解这个请求,然后告诉service层,service层就知道要做什么事了。这时session就开启了。当service层把用户希望得到的信息检索出来后,session差不多就完成了,也就结束了。这时用户希望得到的信息--通过包装我们可以说至少是一个对象对hibernate来说就是个脱管对象了。所以就会出上我在三楼说的那样两种情况。当然那种会有异常的情况是基于hibernate的惰性加裁,而别一种情况就是可能出现又打开另一个session,然后把这个脱管对象又放到这个新的session中去了。应该说我这里提到的后一种情况是一种解决方案,这种方案可能导致频繁打开关闭session的情况。那还有一种解决方案就是在service层还没关闭session前把检过出来的对象通过copyproperiys()方法拷贝一个副本给web控制层。这时关闭了session就不会出现A对象中的关联对象B对象只是代理对象是吧,但是这种方案也有不足的地方,如果每个用户请求都是这样的方式处理,如果A对象关联的对象不只是B对象那么简单,那个这个A对象及其关联的对象到了web控制层时就会很庞大!所以这就是我想跟大家讨论的问题所在!

Hibernate自己有缓存,每次请求都通过OpenSessionInView获得你要的对象,不要有什么脱管对象概念。如果你希望对象另外保存在内存中或自己的HttpSession中,那么就取出完整的对象,不要和Hibernate有关系。

如果你的对象复杂,有很多嵌套,那么从业务建模Evans DDD重新设计你的对象,去除不必要的关联,关联就是聚合;使用查询服务来完成特定1:N关系的。

OpenSessionInView实质就是将数据库JDBC Connection移植到Servlet这里提前打开,这是一种变通方式,而且危险确实高,我在Jdon框架中采取的closeSessionInView,就是不要先打开,由持久层打开,然后延迟关闭,这从设计上比较优雅一些。

老师提出的不要有什么脱管对象和不要和hibernate那就是得把整个对象包括其关联的对象完整的取出来放在内存中,是这样吧?还有closeSessionInView听起来是个不错的主意,值得借签。到于DDD,本人现在只是看过大致看了一下,还没完全认真看完,还得再去再学习!谢谢老师的关注!