记一次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(对象);
相关文章
相关标签/搜索