记一次Hibernate错误

 

 错误信息如下:

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

1、看了代码也找不到错,通常都会先搜索一番,然后发现报这个错,主要是因为如下:

使用的是hibernate的saveOrUpdate方法保存实例。saveOrUpdate方法要求ID为null时才执行SAVE,在其它情况下执行UPDATE。在保存实例的时候是新增,但你的ID不为null,所以使用的是UPDATE,但是数据库里没有主键相关的值,所以出现异常。

但是翻来覆去看了N遍代码也没有找到哪里有调用update之类的方法,错误现场是一个查询语句的地方。

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;
    }

2、然后就想到把Sql语句打印出来,看一下具体是执行了什么update语句导致的,于是将Hibernate打印sql的地方配置为true

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

3、然后发现了update的语句

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

这里 实体类 DepartmentVo映射的就是area 表。但是Hibernate只有对对象set值操作之后才会自动执行update语句的,而代码里并没有看到有地方有赋值

 

4、然后把参数值也打印出来,在logback里面添加配置

<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语句的参数值如下:

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]

 

5、然后再把刚刚查询出来的对象打印出来,跟update的值比较一下

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(对象);

 

转载于:https://www.cnblogs.com/ld-swust/p/10478849.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我可以为您提供一些关于Hibernate实战程序的建议和实现方法,您可以参考以下步骤: 1.首先,您需要在Maven或Gradle中添加Hibernate依赖,例如: ``` <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>5.4.10.Final</version> </dependency> ``` 2.然后,您需要设置Hibernate的配置文件hibernate.cfg.xml,其中包含Hibernate数据库连接信息、实体类映射关系、缓存策略等配置。例如: ``` <hibernate-configuration> <session-factory> <!-- 配置数据库连接信息 --> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/testdb</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password">pwd</property> <!-- 配置实体类映射关系 --> <mapping class="com.example.User"/> <!-- 配置缓存策略 --> <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property> <property name="hibernate.cache.use_second_level_cache">true</property> <property name="hibernate.cache.use_query_cache">true</property> </session-factory> </hibernate-configuration> ``` 3.接下来,您可以创建一个实体类,例如User类,该类需要使用Hibernate注解来映射到数据库表中。例如: ``` @Entity @Table(name = "user") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "name") private String name; @Column(name = "age") private Integer age; // ... } ``` 4.最后,您可以使用Hibernate的API来进行数据库操作,例如: ``` // 创建SessionFactory SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory(); // 创建Session Session session = sessionFactory.openSession(); // 开始事务 Transaction tx = session.beginTransaction(); // 保存实体类 User user = new User(); user.setName("Tom"); user.setAge(20); session.save(user); // 提交事务 tx.commit(); // 关闭Session和SessionFactory session.close(); sessionFactory.close(); ``` 以上就是一个简单的Hibernate实战程序的实现步骤,希望对您有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值