论坛首页 Java版 Spring

配置OpenSessionInViewFilter后引起的更新问题

浏览 3094 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
最后更新时间:2007-06-27
这个和OpenSessionInViewFilter没有关系,很可能是你用到了上一处理过程中遗留下来的对象,在本次处理中就是游离对象了,比如id为1,如果在本次处理中通过查询数据库查出来了id为1的对象,也就是在本次处理的session中持久化了一个id为1的对象,这时如果你对上次留下来的那个游离的对象再更新,因为session中已经持久化了一个id为1的对象,再要把另一个相同id相同类的对象再纳入session中,那显然会报错了。
========================================================================

和OpenSessionInViewFilter还是有一定关系,如果使用OpenSessionInViewFilter,那么前面可能已经执行了一些查询,session中保持了一些对象,在更新游离对象时有可能id撞车;如果不使用OpenSessionInViewFilter,那么如果更新游离对象是一个独立的操作,session是新创建的就不会有问题。

最好的方法是根据id或其他条件从数据库查出对象,再一个属性一个属性的修改,然后更新。
   
0 请登录后投票
最后更新时间:2007-06-21
Godlikeme 写道
不是同名的问题,是id的问题,session关联的同一id的对象只有一个。

嗯,确实是同一个id的问题。
表面上看由于同name,因为我先查询有无叫这个name的company,如果没有的话,相当于没有持久化这个对象,可以进行更新等操作。如果查到数据了,就是持久化了这个对象,然后在进行update操作,当然是不允许的。也就是janh说的这样。
   
0 请登录后投票
最后更新时间:2007-06-21
janh 写道
这个和OpenSessionInViewFilter没有关系,很可能是你用到了上一处理过程中遗留下来的对象,在本次处理中就是游离对象了,比如id为1,如果在本次处理中通过查询数据库查出来了id为1的对象,也就是在本次处理的session中持久化了一个id为1的对象,这时如果你对上次留下来的那个游离的对象再更新,因为session中已经持久化了一个id为1的对象,再要把另一个相同id相同类的对象再纳入session中,那显然会报错了。
========================================================================

和OpenSessionInViewFilter还是有一定关系,如果使用OpenSessionInViewFilter,那么前面可能已经执行了一些查询,session中保持了一些对象,在更新游离对象时有可能id撞车;如果不使用OpenSessionInViewFilter,那么如果更新游离对象是一个独立的操作,session是新创建的就不会有问题。

最好的方法是根据id或其他条件从数据库查出对象,再一个属性一个属性的修改,然后更新。



1、现在已经证实跟OpenSessionInViewFilter没有关系,具体原因就是你说的这样。引起问题的代码看下面,已经贴出。
2、其实OpenSessionInViewFilter是执行一个action时开一个session,直到使用结束,都是本身管理的,所以不存在所谓的手工关闭,个人看法而已。
3、其实现在问题引申到另外一个点上面去了:就是更新一个对象时,判断是否重名(非主键),大家一般用什么办法?

我自己的解决办法,其中id是传进来的(新增的就是null,修改的就是该条的id),hql是根据要添加或更新company相关字段拼起来的:

List<Company> list = companyDAO.getList(hql);
if(id == null && list != null) {
   return true;
   // 说明是新增的company,并且数据库没有该company.name
} else {
   if (list != null) {
      //说明查到数据,但不知是原有的记录还是其他的记录
      for (Company c : list) {
         if (!(c.getId().equals(id)) {
            return true;
            //如果是原有的,则返回true,表明可以更新
              //这步也是引起我1楼问题的所在
         }
      }
   }
}
   
0 请登录后投票
最后更新时间:2007-06-22
我是说使用OpenSessionInViewFilter的session的生命周期比不使用OpenSessionInViewFilter的session的生命周期更长,所以session关联的对象会更多,所以更新游离对象时更容易发生id撞车的事情。

对于更新对象,最好不要将页面过来的对象直接更新,而是用id从数据库中查出持久化的对象,将页面过来的对象当作dto来用,把各个属性值赋到那个查出来的与session关联的对象中,对这个对象进行更新操作。特别对于有多对一关联的对象来说,从页面来的对象中应该不包含多对一的一方吧,这样的方法更好。
   
0 请登录后投票
最后更新时间:2007-06-22
companyService.updateCompany(company);

company是怎么创建的?是自己new的还是从session中取的
如果是自己new很有可能会跟session中的一个company id冲突,造成这种情况
   
0 请登录后投票
最后更新时间:2007-06-22
janh 写道
我是说使用OpenSessionInViewFilter的session的生命周期比不使用OpenSessionInViewFilter的session的生命周期更长,所以session关联的对象会更多,所以更新游离对象时更容易发生id撞车的事情。

对于更新对象,最好不要将页面过来的对象直接更新,而是用id从数据库中查出持久化的对象,将页面过来的对象当作dto来用,把各个属性值赋到那个查出来的与session关联的对象中,对这个对象进行更新操作。特别对于有多对一关联的对象来说,从页面来的对象中应该不包含多对一的一方吧,这样的方法更好。

同意这种方式
这种方式的另外一个优点是可以配置dynamic-update='true'只更新改变过的字段 节省网络开销
   
0 请登录后投票
最后更新时间:2007-06-22
xly_971223 写道
companyService.updateCompany(company);

company是怎么创建的?是自己new的还是从session中取的
如果是自己new很有可能会跟session中的一个company id冲突,造成这种情况


company是由页面传过来的,是new的。
问题在执行update过程中,我有一个操作引起了这个问题:判断“company.name”是否重名,我是取出来比较,估计比较的时候session存在了这样一个id,然后下面在未进行任何操作的情况下立即update才会出问题。
我把判断重名的代码去掉,一切正常。

不知道大家一般如何判断插入或修改的对象中某个属性不能重名?
   
0 请登录后投票
最后更新时间:2007-06-22
xly_971223 写道
janh 写道
我是说使用OpenSessionInViewFilter的session的生命周期比不使用OpenSessionInViewFilter的session的生命周期更长,所以session关联的对象会更多,所以更新游离对象时更容易发生id撞车的事情。

对于更新对象,最好不要将页面过来的对象直接更新,而是用id从数据库中查出持久化的对象,将页面过来的对象当作dto来用,把各个属性值赋到那个查出来的与session关联的对象中,对这个对象进行更新操作。特别对于有多对一关联的对象来说,从页面来的对象中应该不包含多对一的一方吧,这样的方法更好。

同意这种方式
这种方式的另外一个优点是可以配置dynamic-update='true'只更新改变过的字段 节省网络开销


听2位这么一说,确实这种更新的办法不错。dynamic-update我回头用用,呵呵。
   
0 请登录后投票
最后更新时间:2007-06-22
scienceren 写道
xly_971223 写道
janh 写道
我是说使用OpenSessionInViewFilter的session的生命周期比不使用OpenSessionInViewFilter的session的生命周期更长,所以session关联的对象会更多,所以更新游离对象时更容易发生id撞车的事情。

对于更新对象,最好不要将页面过来的对象直接更新,而是用id从数据库中查出持久化的对象,将页面过来的对象当作dto来用,把各个属性值赋到那个查出来的与session关联的对象中,对这个对象进行更新操作。特别对于有多对一关联的对象来说,从页面来的对象中应该不包含多对一的一方吧,这样的方法更好。

同意这种方式
这种方式的另外一个优点是可以配置dynamic-update='true'只更新改变过的字段 节省网络开销


听2位这么一说,确实这种更新的办法不错。dynamic-update我回头用用,呵呵。


记得以前的一个帖子里面写过,动态更新时,hibernate需要对比每一个字段,然后根据情况生成update的sql,虽然sql是效率提高了,但是对比的过程一样是效率很低的,而且,在hibernate官方来说,load before update是推荐做法
   
0 请登录后投票
论坛首页 Java版 Spring

跳转论坛:
JavaEye推荐