網上出現此問題大概緣由有如下幾種: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,即找不到的話就會拋出異常。