现在网上流传的很多ssh架构的系统,包括开源的一些应用系统,很多都用了openSessionInView模式,这样一来,整个编程过程将大大简化。session的生命周期在整个请求范围内有效。我们可以把dao查询出来的有延迟加载属性的对象传递到页面中去。
但是在页面输出内容多的情况下,filter会使用页面缓冲区,这时filter的执行时间就和用户的网速有关,因此openSessionInview有可能造成数据库连接不能及时释放的问题。如果不使用openSessionInView,那么我们一般会配置service层的方法使用事务,也就是说我们要在service层将所有延迟加载的属性
都取出来,放到vo中去,这样我们就需要建一系列的vo对象。严格的说,我们要在service层实现vo和po的转换。保存数据时
action :获取formbean,将formbean转换为vo,save(vo)
service: vo->po,dao.save(po)                      (service层的curd方法都需要用vo做参数?)查询数据时
dao:getList()
servce:遍历list,将list的每一个po转换为vo,有时需要处理po中的明细属性
这样vo和po的转换将带来很多额外的工作。有时感觉很多余。另外有人提出用formbean作为vo,但是formbean是struts的东西,这样vo就和struts耦合,感觉不合理,最重要的是formbean反应的是form提交时的属性,但是查询列表里的对象可能和他的属性并不一样,除非构造一个冗余的formbean来处理输入和输出。vo和form的关系这些问题,期望有高人可以解答。

解决方案 »

  1.   

    楼主研究的很深,在下也看不大明白,只是觉得vo要完全脱离出来可以用自定义JavaBean来实现,事务也可以自己来定义,不要都依靠Spring来解决,这样可能比较方便。
      

  2.   

    楼主太敬业了,我在这里首先佩服一下。
    ssh框架住要是将"表示层"、"逻辑层"、"数据库层"进行清晰分离。在这里重要的是spring。
    你所说的"openSessionInView模式"编程过程未必会大大简化,只是减少了业务或逻辑的交互,利用了可利用的空间
    提高相关的效率。延迟加载一般是提前就会被加载到内存中,就是说 相关对象被放到服务器的内存中,如果想调用
    此对象从内存中获得。性能和效率完全可以保证。
      

  3.   

    struts2 可以解决一部分你的问题.
    那里看不到formbean
      

  4.   

    我觉得应该用spring的事物处理+AOP
      

  5.   

    其实我觉得问题很大程度上在于openSessionInView模式能够很好的利用hibernate的延迟加载。
    如果不使用openSessionInView,我们就需要做一些额外的工作,举例如下:
    public class Goods{
    String id;
    GoodsType type;
    //getter and setter
    }
    如果用openSessionInView
    那么只需要得到List l = GoodsDao.getGoodsList();
    在jsp中,我们可以通过迭代用 good.id ,good.type.name得到物品id,物品类型名称这2个属性如果不用openSessionInView
    那么我们可能需要建一个GoodsVO(日后需要增加一个字段比如价格price,我要改Goods,GoodsForm,现在又要多改一个GoodsVO)
    public class GoodsVO{
    String id;
    String typeName;//页面需要显示type的name如果日后需要显示type的descript,那么我又要在vo加一个属性,对应的service也要改!!
                    而openSessionInview在页面里good.type.descipt就可以了,不用任何改动

    }
    然后我们在service里
    List l = GoodsDao.getGoodsList();
    List result = new ArrayList();
    //已经得到list了,却还要遍历再封装一个vo list
    for(int i=0;i<l.size();i++){
    Goods g = (Goods)l.get(i);
    GoodsVO gv = new GoodsVO();
    gv.setId(g.getId());
    gv.setTypeName(g.getType().getName())
    .....一系列的set方法....
    (增加一个字段,这里又要改)

    result.add(gv);
    }
    对比一下,如果用openSessionInView,代码量和维护量都要比不用少。
    现在已经很明确的知道了openSessionInView存在弊端,需要增加vo,在业务层就获取各个关联的lazy属性然后关闭session
    可是这样感觉好像很多地方都在做重复的复制。
      

  6.   

    formbean可以简化,struct1.3好像有个lazyform的什么东西,可以不用去定义formbean的对象。直接用vo对象去处理
      

  7.   

    很多都用了openSessionInView模式,这样一来,整个编程过程将大大简化
    另外有人提出用formbean作为vo,但是formbean是struts的东西,这样vo就和struts耦合,感觉不合理,最重要的是formbean反应的是form提交时的属性,但是查询列表里的对象可能和他的属性并不一样,除非构造一个冗余的formbean来处理输入和输出。vo和form的关系
    ————————————————————————————————————————————————————————————————————————
    个人觉得如果为了简化编程过程而采取这种方式不太可取,不仅带来了分层的混乱和耦合,而且容易使自己思维混乱,同时也觉得不安全。
    另,20楼的哥们真是.................性情中人啊!
      

  8.   

    struts1的formbean继承了ActionForm类,与struts框架及其容器耦合,所以不能被用做po不过struts1有两种方式能解决这个问题
    1 声明一个对象,然后在formbean中引入这个对象
    2 使用struts1的动态form,引入一个外部对象这个对象,可以是vo、po,因为他是pojo,呵呵以上两种都是最常用的方法。
      

  9.   

    研究的很深啊,这里学习了。有个问题,如果用frombean当作vo,那是不是应该采用动态form
      

  10.   

    前段时间帮一个公司做个东西,
    他们公司是自己的framework,
    他们自己封装的,
    我就感觉其实很多时候没有必要非要哪种框架
    只要能解决问题,并保证效率,使用哪种框架或技术都可以
      

  11.   

    顶9楼,用struts2可使开发简化很多,在struts2中,可以将po和vo简化合为一个action的属性对象(也就是作为action的一个属性),view层和dao可直接通过这个对象联系起来,网页到po的数据类型转换及对象赋值则由struts2的拦截器完成,数据校验由校验器或action的校验方法完成,通过了数据校验的po可直接交由dao处理,至于加载策略的问题,应该是dao类考虑的问题,处于po中的数据,应该由dao保证是准确的。
      

  12.   

    顶9楼,用struts2可使开发简化很多,在struts2中,可以将po和vo简化合为一个action的属性对象(也就是作为action的一个属性),view层和dao可直接通过这个对象联系起来,网页到po的数据类型转换及对象赋值则由struts2的拦截器完成,数据校验由校验器或action的校验方法完成,通过了数据校验的po可直接交由dao处理,至于加载策略的问题,应该是dao类考虑的问题,处于po中的数据,应该由dao保证是准确的。
      

  13.   

    顶9楼,用struts2可使开发简化很多,在struts2中,可以将po和vo简化合为一个action的属性对象(也就是作为action的一个属性),view层和dao可直接通过这个对象联系起来,网页到po的数据类型转换及对象赋值则由struts2的拦截器完成,数据校验由校验器或action的校验方法完成,通过了数据校验的po可直接交由dao处理,至于加载策略的问题,应该是dao类考虑的问题,处于po中的数据,应该由dao保证是准确的。
      

  14.   

    opensessioninview就是为了解决延迟加载session关闭的问题,
    将session的关闭一直延迟到表示层如果想解决这个问题,LZ的方案虽然可行,但是会造成非常大的代码量和vo转换的耗费的时间
    还有一种,就是尽量不用关系连接,不用延迟加载,不过这样也会造成性能问题所以,没有一种方案是最优的
    如果不是对网速要求非常苛刻,建议还是用opensessioninview的好
    如果性能问题跟不上,那就不要用hibernate的好,换别的orm可能更好一点
    归根结底,选合适的就好
      

  15.   

    其实主要问题还是出在延迟加载,
    如果不用延迟加载,同时又设定了关联关系,那么很多时候会做不必要的关联查询
    如果用了延迟加载,又不用openSessioninView,则必须在service层去将需要使用的延迟加载的属性都取一遍
      

  16.   

    struts根本用不着form来封装数据,直接request.getParameter多方便,干嘛给自己找麻烦。
      

  17.   

    默认一定要用延迟加载,否则性能问题很大!
    所以,当你做查询的时候,如果想做关连查询,那么你就手工fetch抓取,比如用createQuery查询
    如果认为opensessioninview效率低的话,就可以这么
      

  18.   

    默认一定要用延迟加载,否则性能问题很大! 
    所以,当你做查询的时候,如果想做关连查询,那么你就手工fetch抓取,比如用createQuery查询 
    如果认为opensessioninview效率低的话,就可以这么
    ----------------------------------------------------
    这样的话,关联其实就没有带来什么便利了,还是要自己去手动查询。
    就是这个地方觉得很矛盾。
    hibernate的延迟加载就是为了能够按需去加载关联对象,可是按照分层的原则,我们又要在service层就把延迟加载的属性确定下来,其实很多时候需要哪些
    属性是在jsp中才确定的
      

  19.   

    有时候我们已经写好了service层,这时候发现有一个页面需要显示某个延迟加载的集合,而我们已经提供的方法并不能实现这个需求,所以我们要去新增一个方法,如果用openSessionInView+延迟加载的话就不用做任何的处理
    例如
    user有 相关订单集合orders,相关文章news,相关资源集合files....
    这些属性一般都是延迟加载的,我们的getUser方法一般都不会去取这些属性,但是我的一个jsp要用,因此就要去加一个方法getUserWithXXX把这些属性先取出来
      

  20.   

    如果session的生命周期在service层结束,我们用关联还能带来多少好处呢?
    直接把那些id的属性都用String表示,然后各种关联的集合,对象都按需要去取应该也不会麻烦多少吧。
    听过很多人说他们的系统里从来不用关联。
      

  21.   

    偶基本上没见过谁用到了HIBERNATE的关联(偶素菜菜) 使用HIBERNATE之后我们更习惯 :“哦 原来数据可以这么查” 但是呢我们完全可以不用这种查询方式么 
      

  22.   


    既然你的系统对性能要求这么苛刻,换ibatis吧,hibernate不是万能的
    taobao用ibatis不也用的挺好的吗
      

  23.   

    "最重要的是formbean反应的是form提交时的属性,但是查询列表里的对象可能和他的属性并不一样,除非构造一个冗余的formbean来处理输入和输出。vo和form的关系 ",在表示方面试下AJAX,SESSEION等SPRING2.0的新特性也试下,不知道能否做到你的要求!
      

  24.   

    struts2 可以解决你的问题,他的普通pojo类就可以处理
      

  25.   

    不知道,随便说说:把Session的生命周期结束到过滤器中。。
      

  26.   

    这不是有struts2吗,为什么要纠结到openSessionInView呢,难道一个框架就把人憋死了吗?那是不是任何一个程序员在完成一个框架的开发以后,在去学习另一个框架时,又要来此纠结一下。这样子要死多少脑细胞呢?我感觉既然有好的东西了,为什么还要用以前的?路过,我打酱油的。