网上出现此问题大概缘由有如下几种:java
可是我本地不是,我是多的一方数据不存在,废话很少先上代码:数据库
// 伪代码
class Class{
@Id
Long id;
@OneToMany(cascade = CascadeType.DETACH,mappedBy = "clazz")
List<Student> students;
public Class(Map<String,Object> param){
// 构建新的对象
Class newClazz = new Class();
newClazz.setId((Long)param.get("id"));
// 构建新的学生对象
List<Map<String,Object>> studentMaps = param.get("students");
students = new ArraryList();
studentMaps.forEach(map -> {
Student st = new Student();
st.setId((Long)map.get("id"));
students.add(st);
})
}
}
class Student{
@Id
Long id;
@ManyToOne(cascade = CascadeType.DETACH)
@JoinColumn(name="class_id")
Class clazz;
}
复制代码
以上是实体类对应的为伪代码,接下来是业务操做:session
class ClassManagerImpl implements IClassManager{
void saveOrUpdate(Map<String,Object> params){
Class newClass = new Class(params);
Class oldClass = classDao.get(newClass.getId());
if(oldClass!=null){
newClass.setCreateDate(oldClass.getCreateDate());
}
classDao.saveOrUpdate(newClass);
}
}
class ClassDaoImpl implements IClassDao{
void saveOrUpdate(Class class){
try {
this.hibernateTemplate.saveOrUpdate(class);
} catch (DuplicateKeyException | NonUniqueObjectException e) {
// 此处merge报出以上bug
this.hibernateTemplate.merge(obj);
}
}
}
复制代码
以上的代码,在出现如下这种状况:app
Class已存在,可是他关联的Student对象不存在ide
会报两个错:this
出现第一个问题是因为调用saveOrUpdate()时因为咱们调用get方法时已查询过一次Class对象,可是咱们更新时又是建立的新对象,因此会报错。spa
出现第二个问题的缘由是由于咱们捕获了第一个异常:NonUniqueObjectException,而后调用merge()方法,merge方法用于合并属性,当咱们有一对多等关联配置时,他会去数据库查询相应的数据来进行数据合并,若是关联数据不存在就会出错。hibernate
举例:code
id为1的Class 存在数据库中,此处数据库中尚未Student数据。咱们经过业务更新ID为1的Class,同时新增一个Student对象。此时就会报错xml
解决办法为增长not-found配置:
注解方式:
class Class{
@Id
Long id;
@OneToMany(cascade = CascadeType.DETACH,mappedBy = "clazz")
@NotFound(action= NotFoundAction.IGNORE)
List<Student> students;
}
复制代码
XML配置方式:
<class name="Class" table="class">
<id column="id" name="id" type="java.lang.Long"><generator class="assigned" /></id>
<bag name="students" cascade="none">
<key>class_id</key>
<one-to-many not-found="ignore" class="Student" />
</bag>
</class>
复制代码
该参数默认为EXCEPTION,即找不到的话就会抛出异常。