記一次Hibernate錯誤

 

 錯誤信息以下:sql

Caused by: org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1

一、看了代碼也找不到錯,一般都會先搜索一番,而後發現報這個錯,主要是由於以下:數據庫

使用的是hibernate的saveOrUpdate方法保存實例。saveOrUpdate方法要求ID爲null時才執行SAVE,在其它狀況下執行UPDATE。在保存實例的時候是新增,但你的ID不爲null,因此使用的是UPDATE,可是數據庫裏沒有主鍵相關的值,因此出現異常。spa

可是翻來覆去看了N遍代碼也沒有找到哪裏有調用update之類的方法,錯誤現場是一個查詢語句的地方。hibernate

public DepartmentVo getDepartmentVo(String deptCode) {
        SQLQuery query = getCurrentSession().createSQLQuery("select * from department where DEPT_CODE = ?");
        query.setParameter(0, deptCode);
        query.setMaxResults(1);
        
        DepartmentVo departmentVo = (DepartmentVo) query.addEntity(DepartmentVo.class).uniqueResult(); // 斷點調試時,此處報錯
        return departmentVo;
    }

二、而後就想到把Sql語句打印出來,看一下具體是執行了什麼update語句致使的,因而將Hibernate打印sql的地方配置爲true調試

<prop key="hibernate.show_sql">${hibernate.show_sql:true}</prop>

三、而後發現了update的語句code

  update
        area 
    set
        DEPT_CODE=?,
        DEPT_NAME=?,
        PARENT_DEPT_CODE=?,
        TYPE_LEVEL=? 
    where
        DEPT_ID=?

這裏 實體類 DepartmentVo映射的就是area 表。可是Hibernate只有對對象set值操做以後纔會自動執行update語句的,而代碼裏並無看到有地方有賦值對象

 

四、而後把參數值也打印出來,在logback裏面添加配置blog

<logger name="org.hibernate.type.descriptor.sql.BasicBinder">  
    <level value="TRACE" />
</logger><logger name="org.hibernate.type.descriptor.sql.BasicExtractor">  
    <level value="DEBUG" />
</logger>

打印update語句的參數值以下:ip

binding parameter [1] as [VARCHAR] - [888M]
binding parameter [2] as [VARCHAR] - [xxxx/888M]
binding parameter [3] as [VARCHAR] - [888M]
binding parameter [4] as [VARCHAR] - [3]
binding parameter [5] as [BIGINT] - [2817]

 

五、而後再把剛剛查詢出來的對象打印出來,跟update的值比較一下get

DepartmentVo [deptId=2817, deptCode=888M, deptName=xxxx, parentCode=888M, typeLevel=3]

最終發現了對象先後的值果真不同,而後deptId=2817在表area又不存在,因此報錯。

最後在DepartmentVo中發現

    public String getDeptName() {
        if (null != deptCode && null != deptName)
        {
            return deptName + "/" + deptCode;
        }
        return deptName;
    }

因此,按照這個,addEntity方法大概是用的反射吧~~~

 

解決方法的話,能夠用

getCurrentSession().evict(對象);
相關文章
相關標籤/搜索