關於hibernate的 No row with the given identifier exists

網上出現此問題大概緣由有如下幾種: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

  • A different object with the same identifier value was already associated with the session
  • No row with the given identifier exists

出現第一個問題是因爲調用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,即找不到的話就會拋出異常。

相關文章
相關標籤/搜索