|
精华帖 (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或其他条件从数据库查出对象,再一个属性一个属性的修改,然后更新。 |
|
| 返回顶楼 | |
|
最后更新时间:2007-06-21
Godlikeme 写道 不是同名的问题,是id的问题,session关联的同一id的对象只有一个。
嗯,确实是同一个id的问题。 表面上看由于同name,因为我先查询有无叫这个name的company,如果没有的话,相当于没有持久化这个对象,可以进行更新等操作。如果查到数据了,就是持久化了这个对象,然后在进行update操作,当然是不允许的。也就是janh说的这样。 |
|
| 返回顶楼 | |
|
最后更新时间: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楼问题的所在
}
}
}
}
|
|
| 返回顶楼 | |
|
最后更新时间:2007-06-22
我是说使用OpenSessionInViewFilter的session的生命周期比不使用OpenSessionInViewFilter的session的生命周期更长,所以session关联的对象会更多,所以更新游离对象时更容易发生id撞车的事情。
对于更新对象,最好不要将页面过来的对象直接更新,而是用id从数据库中查出持久化的对象,将页面过来的对象当作dto来用,把各个属性值赋到那个查出来的与session关联的对象中,对这个对象进行更新操作。特别对于有多对一关联的对象来说,从页面来的对象中应该不包含多对一的一方吧,这样的方法更好。 |
|
| 返回顶楼 | |
|
最后更新时间:2007-06-22
companyService.updateCompany(company); company是怎么创建的?是自己new的还是从session中取的 如果是自己new很有可能会跟session中的一个company id冲突,造成这种情况 |
|
| 返回顶楼 | |
|
最后更新时间:2007-06-22
janh 写道 我是说使用OpenSessionInViewFilter的session的生命周期比不使用OpenSessionInViewFilter的session的生命周期更长,所以session关联的对象会更多,所以更新游离对象时更容易发生id撞车的事情。
对于更新对象,最好不要将页面过来的对象直接更新,而是用id从数据库中查出持久化的对象,将页面过来的对象当作dto来用,把各个属性值赋到那个查出来的与session关联的对象中,对这个对象进行更新操作。特别对于有多对一关联的对象来说,从页面来的对象中应该不包含多对一的一方吧,这样的方法更好。 同意这种方式 这种方式的另外一个优点是可以配置dynamic-update='true'只更新改变过的字段 节省网络开销 |
|
| 返回顶楼 | |
|
最后更新时间:2007-06-22
xly_971223 写道 companyService.updateCompany(company); company是怎么创建的?是自己new的还是从session中取的 如果是自己new很有可能会跟session中的一个company id冲突,造成这种情况 company是由页面传过来的,是new的。 问题在执行update过程中,我有一个操作引起了这个问题:判断“company.name”是否重名,我是取出来比较,估计比较的时候session存在了这样一个id,然后下面在未进行任何操作的情况下立即update才会出问题。 我把判断重名的代码去掉,一切正常。 不知道大家一般如何判断插入或修改的对象中某个属性不能重名? |
|
| 返回顶楼 | |
|
最后更新时间:2007-06-22
xly_971223 写道 janh 写道 我是说使用OpenSessionInViewFilter的session的生命周期比不使用OpenSessionInViewFilter的session的生命周期更长,所以session关联的对象会更多,所以更新游离对象时更容易发生id撞车的事情。
对于更新对象,最好不要将页面过来的对象直接更新,而是用id从数据库中查出持久化的对象,将页面过来的对象当作dto来用,把各个属性值赋到那个查出来的与session关联的对象中,对这个对象进行更新操作。特别对于有多对一关联的对象来说,从页面来的对象中应该不包含多对一的一方吧,这样的方法更好。 同意这种方式 这种方式的另外一个优点是可以配置dynamic-update='true'只更新改变过的字段 节省网络开销 听2位这么一说,确实这种更新的办法不错。dynamic-update我回头用用,呵呵。 |
|
| 返回顶楼 | |
|
最后更新时间: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是推荐做法 |
|
| 返回顶楼 | |







