Hibernate持久化异常:重复持久化已删除旧实体问题咨询
嘿,这个问题我刚入门Hibernate的时候踩过一模一样的坑!你遇到的情况大概率是Hibernate的缓存机制在搞鬼,或者程序里的实体对象没有正确重建。给你理清楚可能的原因和对应的解决办法:
可能的原因及解决步骤
1. Session一级缓存没清空
Hibernate的Session默认会缓存它加载或持久化过的对象,如果你在程序里没有及时关闭旧Session,而是复用了同一个实例,那就算你手动删了数据库里的数据,Session缓存里的旧对象依然存在。再次执行持久化时,这些缓存的旧对象会被重新写入数据库,就出现了新旧数据一起存的情况。
解决办法:
- 严格遵循“一次操作一个Session”的原则,每次操作完成后调用
session.close()关闭Session; - 如果必须复用Session,在重新执行持久化前手动清空缓存:
// 清空当前Session的所有缓存对象 session.clear();
2. 二级缓存未失效
如果你配置了Hibernate的二级缓存(比如Ehcache、Redis这类),缓存数据会存在SessionFactory级别,单个Session关闭也不会清空它。手动删库后缓存没有同步更新,程序再次运行时就会把缓存里的旧对象重新写入数据库。
解决办法:
- 如果不需要二级缓存,直接在Hibernate配置文件里关闭它:
<!-- 关闭二级缓存 --> <property name="hibernate.cache.use_second_level_cache">false</property> - 如果必须使用二级缓存,手动删库后要清空整个二级缓存:
// 清空SessionFactory下所有缓存区域的数据 sessionFactory.getCache().evictAllRegions();
3. 程序复用了旧的实体对象
可能你的程序里没有在每次运行时创建全新的实体对象,而是复用了之前运行时生成的对象实例(比如把实体对象定义成了全局静态变量)。就算你删了数据库数据,内存里的旧对象依然存在,再次执行持久化时就会被重新保存。
解决办法:
- 确保每次执行持久化操作时,都创建全新的实体对象实例。比如把对象创建的代码放在每次运行的方法内部,而不是类的静态属性里。
4. 数据库事务未提交(小概率)
虽然你说确认表为空了,但还是可以排查下:手动删除数据时有没有提交事务?比如用Oracle客户端删数据后没点提交按钮,数据库里的数据其实没真正删除。可以手动执行COMMIT;语句确认,或者把客户端设置成自动提交模式。
内容的提问来源于stack exchange,提问作者DanielBK




