我尝试了以下代码:
Student s1 = (Student) s.load(Student.class, 5); // this records not there in DB
try {
s1.setName("Kaushik1");
} catch (ObjectNotFoundException e) {
s1 = new Student();
s1.setId(5);
s1.setName("trying1");
}
s.saveOrUpdate(s1);
Student s2 = (Student) s.load(Student.class, 5);
try {
s2.setName("Kaushik2");
} catch (ObjectNotFoundException e) {
//Why should it throw ObjectNotFoundException now
s2 = new Student();
s2.setId(5);
s2.setName("trying2");
}
s.saveOrUpdate(s2); //Why it throws NonUniqueObjectException
我使用load
从ID为#5的数据库中提取记录。记录不存在。然后我尝试在对象上调用setter,它抛出异常。同意!!
由于记录不存在,我创建了一个新对象并调用saveOrUpdate()
。所以现在我假设ID#5的对象在会话缓存中。
现在我再次尝试为ID#5调用load()
方法并调用其setter。它再次抛出ObjectNotFoundException。
问题1
为什么它无法从会话缓存中选择记录?
当我创建新对象并尝试致电saveOrUpdate()
时,它会提供NonUniqueObjectException
org.hibernate.NonUniqueObjectException:与...不同的对象 相同的标识符值已与会话关联: [com.cts.closr.Student#5]
它抛出了ObjectNotFoundException,现在说“已经与会话关联的对象”。这不矛盾吗?
问题2
这是否意味着load()
方法永远不会检查会话上下文?它总是取自DB?
那么在这种情况下我必须使用get()
方法?
答案 0 :(得分:3)
如果Session抛出异常(包括任何SQLException),则立即回滚数据库事务,调用Session.close()并丢弃Session实例。 Session的某些方法不会使会话保持一致状态。 Hibernate抛出的异常都不能被视为可恢复的。
因此,使用Session.load()
,捕获异常并继续使用会话是一个很大的禁忌。当您认为对象必须存在于数据库中时必须使用Session.load()
,如果不存在则必须抛出异常。如果您不确定该对象是否存在,请使用Session.get()
,测试返回的对象是否为null,并采取相应的行动。
答案 1 :(得分:0)
"现在我再次尝试为ID#5"调用load()方法,我相信你输错了。
Student s2 = (Student)s.load(Student.class, 6);
应该是
Student s2 = (Student)s.load(Student.class, 5);