日期:2014-05-19  浏览次数:20792 次

SSH架构增删改查奇怪问题
SSH版本:
struts 2.2.1
hibernate 3
spring 3.0.4

同一个项目里面有一个用户的增删改查流程,有一个产品类型的增删改查流程。用户的那个没有问题,产品类型的出了这样一个问题:
先新增一个,然后删除,再新增的时候在页面报错500,错误信息如下:
org.springframework.orm.hibernate3.HibernateSystemException: could not reassociate uninitialized transient collection; nested exception is org.hibernate.HibernateException: could not reassociate uninitialized transient collection
查了网上的资料,在spring的配置文件中增加了scope="prototype",如下:
XML code

<bean id="furnituretypeAction" class="com.redwood.action.FurnituretypeAction" scope="prototype">
        <property name="furnituretypeBiz" ref="furnituretypeBiz"></property>
    </bean>


然后问题解决了,但是新的问题就又出来了。

对产品类型中的一个进行修改时,发现页面又报另外的错误了:
org.springframework.dao.InvalidDataAccessApiUsageException: The given object has a null identifier: com.redwood.entity.Furnituretype; nested exception is org.hibernate.TransientObjectException: The given object has a null identifier: com.redwood.entity.Furnituretype


在spring的xml里面我分别加scope="prototype",和不加scope="prototype",用断点调试发现:
不加scope="prototype",报错是因为新增时,主键居然不为null;
相反,增加scope="prototype"后,进入update方法后,主键居然为null。


最后的解决方法:我在修改的那个页面增加了一个隐藏表单域,把主键取出来,有用表单提交给action后问题彻底解决!




我的问题是:
1.我最后的这种处理方式是否合理?
2.为什么会出现这种问题?
3.为什么用户管理的那个增删改查流程就没出问题?
4.求解释,谢谢!

------解决方案--------------------
我的问题是:
1.我最后的这种处理方式是否合理?
也算合理,只是有点奇怪update时为什么你的主key是null,你的页面信息和你的action是怎么关联的?一般如果你的页面使用的是action的某个entity,那么提交的时候,这个entity的信息是都能自动取到的,想象不到你的key是怎么丢失的,这个要看你的jsp是怎么写的。


2.为什么会出现这种问题?
如果没有scope="prototype",default就是sinleton,也就是单实例,那么所有的处理用的是同一个action,那么action里面的entity信息可能会冲突

3.为什么用户管理的那个增删改查流程就没出问题?
这个要查看你的jsp和action的代码才能知道

4.求解释,谢谢!


------解决方案--------------------
加了scope="prototype“之后,保证action不是单例的,每提交一次请求,都创建一个action实例。

开始楼主没有加,新增时主键不空,因为action是单例的,再次新增得到的主键是刚才删掉的那条记录的主键。

在form上写一个隐藏域,来放置主键,这种方式也可以。
------解决方案--------------------
从你的现象来看,是上一个action转到jsp,然后提交到下一个action时,valuestack 内容没有传递,查了一下,好像只有chain result方式chain拦截器会复制valuestack,默认的dispatcher方式是params拦截器把参数设置到valuestack里,所以页面有传递的参数action才能取到,也就是上一个action的valuestack信息丢失,即id信息丢失,所以你用隐藏域的时候,隐藏域取出了上一个action的valuestack的id信息,提交时当做参数传递到了下一个action的valuestack里,所以就不出错了。这个只能有时间再去看看研究一下整个请求过程的源码了。默认的dispatcher方式是传递request/response的,LZ可以把id或整个对象信息保存到request或session里(attribute),然后在action里取出来也可以。

------解决方案--------------------
可以添加一个隐藏域