多对一存储顺序以及问题object references an unsaved transient instance - save the transient instance。。。

异常1:not-null property references a null or transient value
解决方法:将“一对多”关系中的“一”方,not-null设置为false
(参考资料:http://www.thearcmind.com/confluence/pages/viewpage.action?pageId=212)

异常2:org.hibernate.TransientObjectException: object references an unsaved transient instance
解决方法:cascade="save-update,persist"
(参考资料:http://www.laliluna.de/254.html)

异常3:org.hibernate.QueryException: could not resolve property
解决方法:"from Category category where category.userID = :userID"修改为"from Category category whereuserID = :userID"或者"from Category category where category.user.id = :userID"
(参考资料:http://www.laliluna.de/277.html)

异常4:could not initialize proxy - the owning Session was closed
解决方法:设置lazyfalse
(参考资料:http://forum.springframework.org/showthread.php?t=27993)

异常2我在应用中碰到了这样的问题:

有三个表:userInfo deptmentInfo role

userInfo 与deptmentInfo为many to one

userInfo 与role为many to one

下面为保存UserInfo对象时的代码:

DeptmentInfo dept = new DeptmentInfo();
dept.setDeptName(deptName);

Role role = new Role();
role.setRoleName(roleName);

UserInfo user = new UserInfo();
user.setUserName(userName);
user.setUserSex(userSex);
user.setDuty(duty);
user.setPhone(phone);
user.setMobileNum(mobileNum);
user.setEmail(email);
user.setQq(qq);
user.setMsn(msn);
user.setAdress(adress);
user.setDeptmentInfo(dept);
user.setRole(role);

dao.save(user);

执行时有错:org.hibernate.TransientObjectException: object references an unsaved transient instance

于是改了UserInfo.hbm.xml的一些地方

如下:

<many-to-one name="role" class="com.oa.domain.Role"
cascade="save-update,persist" fetch="select">
<column name="ROLE_ID" precision="22" scale="0" />
</many-to-one>
<many-to-one name="deptmentInfo"
class="com.oa.domain.DeptmentInfo" cascade="save-update,persist"
fetch="select">
<column name="DEPT_ID" precision="22" scale="0" />
</many-to-one>

加了上面红色部分的,就OK了,能保存了。

 

多对一存储顺序

Hibernate多对一关联映射原理、映射方法和数据的保存 本文由 arthinking 发表于724 天前 ⁄ J2EE 暂无评论 ⁄ 被围观 3,264 views+

Hibernate的多对一关联映射实现的基本原理就是:

在多的一端加入一个外键,指向一的一端,映射完成之后使得加载多的一端数据的同时能把关联的一的一端的数据加载上来。

两个类实现多对一的关联映射步骤:
User类作为一的一端:
public class User {

	private String userEmail;
	private String userPasswd;
	public String getUserEmail() {
		return userEmail;
	}
	public void setUserEmail(String userEmail) {
		this.userEmail = userEmail;
	}
	public String getUserPasswd() {
		return userPasswd;
	}	
}
QuestionAnswer类作为多的一端,则需要加入一个User作为外键:
public class QuestionAnswer {

	private int answerId;
	private String answerContent;
	private User answerAnswerer;
	public int getAnswerId() {
		return answerId;
	}
	public void setAnswerId(int answerId) {
		this.answerId = answerId;
	}
	public String getAnswerContent() {
		return answerContent;
	}
	public void setAnswerContent(String answerContent) {
		this.answerContent = answerContent;
	}
	public void setAnswerAnswerer(StudentInfo answerAnswerer) {
		this.answerAnswerer = answerAnswerer;
	}
}
User类的映射配置如下:
<hibernate-mapping>
<class name="com.exam.entity.User" table="exam_user" lazy="false">
	<id name="userEmail" column="user_email"></id>
	<discriminator column="user_type" type="string"/>
	<property name="userPasswd" column="user_passwd" length="20"/>
</class>
</hibernate-mapping>
QuestionAnswer类的映射配置如下:
<hibernate-mapping>
	<class name="com.exam.entity.QuestionAnswer" table="exam_question_answer">
		<id name="answerId" column="answer_id" type="int">
			<generator class="increment" />
		</id>
		<property name="answerContent" column="answer_content" type="text" />		
		<many-to-one name="answerAnswerer" column="question_answer"/>
	</class>
</hibernate-mapping>

从上面的两个配置文件可以看出,多对一的关联映射只需要在多的一端配置一个<many-to-one>标签就可以了,如上面QuestionAnswer类的配置生成的表的question_answer为指向一的一端的外键。

关于多对一关联保存需要注意的事项

按照上面的配置保存数据时,需要先保存User,让Transient状态的User对象变成Persistent状态,才能保存QuestionAnswer,因为只有User变成了Persistent状态之后QuestionAnswer对象才能获取到User的主键作为外键关联,Persistent状态的对象不能引用Transient状态的对象。代码如下:

User user = new User();
user.setUserEmail("arthinking@qq.com");
user.setUserPasswd("arthinking");
session.save(user);

QuestionAnswer answer = new QuestionAnswer();
answer.setAnswerContent("Answer!");
answer.setAnswerAnswerer(user);
session.save(answer);
或者可以设置级联操作:

在多的一端的<many-to-one>标签设置级联属性:

<many-to-one name="answerAnswerer" column="question_answer" cascade="save-update"/>

这样就表示级联保存和级联更新,就会不用显示save(user)了,而是自动级联保存。

Cascade可以的取值为:

all:代表所有情况都进行级联操作
none:不进行级联操作
save-update:保存或更新时进行级联操作
delete:级联删除

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值