论坛首页 Java企业应用论坛

求助Hibernate的单向Many-to-one关系问题。

浏览 11895 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-08-15  
songxh2 写道
janh 写道
修改对象应该在持久化对象的基础上进行修改。
根据id,get获取到对应的持久化对象,再设置要改变的属性值。
关联对象也同样,根据父id,get获取到anotherParent,再child.setParent(anotherParent);


谢谢!说的有理,建议加50分。


但是还是发现问题依然存在!!!!!

我如你所说添加了如下修改方式代码,(其实我原来也做过这个测试,只是不很确定..)

public String update() {
	try {
		//得到新的Id及其持久化对象p,并重新设置child的parent
		Integer pid=child.getParent().getId();
		Parent p=childDAO.getParentById(pid);
		child.setParent(p);

		childDAO.update(child);//此步依然出现错误!!!!
		return "success";
	} catch (RuntimeException e) {
		return "success";
	}
}



错误原因还是:
org.hibernate.HibernateException: identifier of an instance of test.Parent was altered from 1 to 2

不得其解,难道不是不能修改二级对象的id,而是其他原因?比如单向many-to-one关联不能更新关联关系?
0 请登录后投票
   发表时间:2007-08-15  
好像你的parent对象一直在session的管理之下,是一个持久化对象,而并非如你所说的 “只对parent的id属性设置了值,其他值都为空”的一个临时对象,这样虽然没有对parent对象做更新操作,但是当事务提交时,hibernate会自动把对持久化对象的修改保存到数据库中,检查发现id发生了改变,所以报错。

你的对象为什么一直在session的管理之下呢,是每次request到来时提前准备好的还是每次session都不关?
0 请登录后投票
   发表时间:2007-08-15  
引用
好像你的parent对象一直在session的管理之下,是一个持久化对象,而并非如你所说的 “只对parent的id属性设置了值,其他值都为空”的一个临时对象,这样虽然没有对parent对象做更新操作,但是当事务提交时,hibernate会自动把对持久化对象的修改保存到数据库中,检查发现id发生了改变,所以报错。

你的对象为什么一直在session的管理之下呢,是每次request到来时提前准备好的还是每次session都不关?


我用了 在web.xml中用了Spring 的 opensessionviewFilter过滤器的,在web应用的时候是打开的。

	<filter>
		<filter-name>OpenSessionInViewFilter</filter-name>
		<filter-class>
			org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
		</filter-class>
		<init-param>
			<param-name>singleSession</param-name>
			<param-value>true</param-value>
		</init-param>
	</filter>
0 请登录后投票
   发表时间:2007-08-16  
问题基本解决,问题在于jsf的backingbean对象更新机制。。。需要用如下方法避免。

 /* 用户提交页面时,backing bean 的getChild()方法应该提供一个临时对象让jsf来组装更新数据比较合适,
 * 因为jsf恢复数据时首先会用这个方法取个原始对象,然后在这个对象的基础上组装新的数据。
 * 注意一定先提供一个临时对象而非持久化对象,因为在组装数据时,会用新数据替换旧数据,
 * 如果被替换的是持久化对象及其子对象的Id值时(比如child.parent.id),其实你可能只是是想替换与parent的关系,
 * 但jsf系统并不知道你是想要建立新的关系,所以会抛出子对象的Id被强制修改的错误!而持久化对象的Id值是不能被更改的。

 * backing bean 的getChild()方法必须在用户提交页面时应该提供一个临时对象,jsf恢复数据会用这个方法取原始对象,注意一定先提供一个临时对象而非持久化对象,
 * 因为在组装数据时,会用新数据替换旧数据,如果被替换的是持久化对象,在替换子对象关系时,会检查到子对象的Id被强制修改的错误!
 */
public Child getChild() {
	if(child==null){
		//child=(Child)childDAO.getChild(new Integer(4));不能直接实例化session对像,不然jsf会强制更新这个持久化对象的任何值,碰到many-to-one的关系更新,它也会认为是修改原来的持久化对象(应该是替换不是修改),而在修改id值时会抛出错误,无法保存数据。
		child=new Child();  //临时对象
	}
return child;
}
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics