`
风云无浪
  • 浏览: 15167 次
社区版块
存档分类
最新评论

Hibernate数据delete时容易忽略的问题

阅读更多
在主线程通过hibernate的find查询到数据后,把list里数据分别加入到新的list中,然后给子线程处理,子线程在执行getHibernateTemplate().delete(o)的时候,就可能会出现org.hibernate.StaleStateException。

我觉得这个异常出现的原因和内存回收有关系,在内存回收的时候。在session关闭的时候,这些数据会变成游离态,如果JAVA虚拟机没有进行垃圾回收的话,在执行delete操作时是没问题的。如果内存不够,或者有频繁的其他操作影响垃圾回收了,那在执行delete操作时就会出现这个问题。

另外,如果直接通过new一个object,生成主键之类的数据,直接delete数据,基本上也会出现这个问题。

解决的方法可以是:在每次的delete之前,先根据主键进行查询操作,如果不为null,再进行delete操作。

另外,直接通过sql进行delete操作应该也可以。update,save等操作应该也是同一个问题。


另外欢迎大家提其他的解决方案。


Hibernate: delete from PA_THIRDLOG where streamNumber=?           
Hibernate: delete from PA_THIRDLOG where streamNumber=?          
ERROR  - Could not synchronize database state with session                
org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1         
    at org.hibernate.jdbc.Expectations$BasicExpectation.checkBatched(Expectations.java:61)       
    at org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:46)    
    at org.hibernate.jdbc.NonBatchingBatcher.addToBatch(NonBatchingBatcher.java:24)                 
    at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:2525)     
    at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:2702)    
    at org.hibernate.action.EntityDeleteAction.execute(EntityDeleteAction.java:77)        
    at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:279)             
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263)       
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:172)       
    at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)       
    at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)                 
    at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)                               
    at org.springframework.orm.hibernate3.HibernateAccessor.flushIfNecessary(HibernateAccessor.java:390)          
    at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:420)           
    at org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:374)       
    at org.springframework.orm.hibernate3.HibernateTemplate.delete(HibernateTemplate.java:846)          
    at org.springframework.orm.hibernate3.HibernateTemplate.delete(HibernateTemplate.java:842)  

ERROR  - Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1; nested exception is org.hibernate.StaleStateException: 

Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1      
org.springframework.orm.hibernate3.HibernateOptimisticLockingFailureException: Batch update returned unexpected row count from update [0]; actual row count: 

0; expected: 1; nested exception is org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; 

expected: 1
    at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:672)    
    at org.springframework.orm.hibernate3.HibernateAccessor.convertHibernateAccessException(HibernateAccessor.java:412)       
    at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:424)          
    at org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:374)      
    at org.springframework.orm.hibernate3.HibernateTemplate.delete(HibernateTemplate.java:846)           
    at org.springframework.orm.hibernate3.HibernateTemplate.delete(HibernateTemplate.java:842)   
1
0
分享到:
评论
12 楼 风云无浪 2012-10-21  
jinnianshilongnian 写道

不讨论了。
我觉得你对垃圾回收 和 hibernate状态改变理解有偏差。 解决了就好了

垃圾回收的时候,不是清理了内存数据,而是清理hibernate的session中缓存的非持久态内容的索引吧,就导致了这个StaleStateException,session内容不匹配。
现在的话,先getObject再deleteObject在一些极端的情况下,还是会出现问题。现在只有试试用纯sql根据id删除了,等测试组再测试下观察观察再讨论吧。
11 楼 jinnianshilongnian 2012-09-29  
风云无浪 写道
jinnianshilongnian 写道

你都拿到这个对象了 怎么可能垃圾回收  没有引用的对象才会垃圾收集

是垃圾回收的时候清理的hibernate非持久态的数据

不讨论了。
我觉得你对垃圾回收 和 hibernate状态改变理解有偏差。 解决了就好了
10 楼 风云无浪 2012-09-29  
jinnianshilongnian 写道

你都拿到这个对象了 怎么可能垃圾回收  没有引用的对象才会垃圾收集

是垃圾回收的时候清理的hibernate非持久态的数据
9 楼 jinnianshilongnian 2012-09-28  
风云无浪 写道
jinnianshilongnian 写道

跟状态无关 delete方法没有要求model必须是什么状态的

是不要求状态,但是游离态会被垃圾回收了,所以getHibernateTemplate().delete(o)就找不到了。
先getHibernateTemplate().get(class,id)后再进行getHibernateTemplate().delete(o)在40W数据处理的时候没啥问题。但是连接外部socket异常的时候,也还是会出问题。
现在只有试试用sql语句删除了。


你都拿到这个对象了 怎么可能垃圾回收  没有引用的对象才会垃圾收集
8 楼 风云无浪 2012-09-28  
jinnianshilongnian 写道

跟状态无关 delete方法没有要求model必须是什么状态的

是不要求状态,但是游离态会被垃圾回收了,所以getHibernateTemplate().delete(o)就找不到了。
先getHibernateTemplate().get(class,id)后再进行getHibernateTemplate().delete(o)在40W数据处理的时候没啥问题。但是连接外部socket异常的时候,也还是会出问题。
现在只有试试用sql语句删除了。

7 楼 jinnianshilongnian 2012-09-28  
风云无浪 写道
jinnianshilongnian 写道
你可以禁用缓存然后测试看看是不是有问题。
你先查一次 如果缓存中有还是能命中的 所以此处可以肯定不是缓存的问题。
不知道你4w数据怎么分的,不好下结论。

其实我说缓存也不准确。应该是hibernate的数据状态,持久态应该是在session.close后就结束了,就变成了游离态,所以就会被JVM回收。map的频繁delete操作就可能触发了垃圾回收。
再查一次的话,就会从游离态变成持久态,就不会有问题了。
4W数据的话,是每次从表里读出来2000的数据,然后分给各个线程(用的是newFixedThreadPool),所以要加到map里或者set里判重,不重复发给子线程。
关于hibernate的持久态、游离态、托管态在什么时候转换,和spring管理的session啥时候触发这些状态的转换,我也不清楚。


4W数据的话,是每次从表里读出来2000的数据,然后分给各个线程(用的是newFixedThreadPool),所以要加到map里或者set里判重,不重复发给子线程。
这才是根本问题, 不重复发。

跟状态无关 delete方法没有要求model必须是什么状态的
6 楼 风云无浪 2012-09-27  
jinnianshilongnian 写道
你可以禁用缓存然后测试看看是不是有问题。
你先查一次 如果缓存中有还是能命中的 所以此处可以肯定不是缓存的问题。
不知道你4w数据怎么分的,不好下结论。

其实我说缓存也不准确。应该是hibernate的数据状态,持久态应该是在session.close后就结束了,就变成了游离态,所以就会被JVM回收。map的频繁delete操作就可能触发了垃圾回收。
再查一次的话,就会从游离态变成持久态,就不会有问题了。
4W数据的话,是每次从表里读出来2000的数据,然后分给各个线程(用的是newFixedThreadPool),所以要加到map里或者set里判重,不重复发给子线程。
关于hibernate的持久态、游离态、托管态在什么时候转换,和spring管理的session啥时候触发这些状态的转换,我也不清楚。
5 楼 jinnianshilongnian 2012-09-27  
这绝对是缓存的问题,我还没这么弱让sql执行两次啊:  你可以禁用缓存然后测试看看是不是有问题。

我最终的处理方法就是在getHibernateTemplate().delete(o)前,先查询一次,如果不为null,再执行删除,然后也在map里进行删除。 
你先查一次 如果缓存中有还是能命中的 所以此处可以肯定不是缓存的问题。



不知道你4w数据怎么分的,不好下结论。
4 楼 风云无浪 2012-09-27  
jinnianshilongnian 写道

Hibernate: delete from PA_THIRDLOG where streamNumber=?  是执行了两次 还是日志打印重复了? 
此处很明显sql执行了。 怀疑删除执行了两次。

那个两次可能是不同线程打印出来的。
这绝对是缓存的问题,我还没这么弱让sql执行两次啊。。
这么说吧,我这个是处理4万数据时候出的问题。我在主线程里把4万个数据分给100个线程。
线程处理的数据我加到ConcurrentHashMap里了(其他的多线程容器也一样),线程处理完一条数据,就在map里删掉相应的记录。这时用getHibernateTemplate().delete(o)时就会有这个异常。如果不在map里删掉相应的记录,就不会有这个异常。所以我怀疑是垃圾回收造成的非持久态数据的清理。

我最终的处理方法就是在getHibernateTemplate().delete(o)前,先查询一次,如果不为null,再执行删除,然后也在map里进行删除。跑40W数据也没出现问题

3 楼 jinnianshilongnian 2012-09-27  
1、垃圾回收不就是内存回收么?回收的是hibernate的缓存,不是数据,这个是由于hibernate缓存的数据不一致造成。

hibernate缓存的数据是需要过期才能垃圾回收的。

2、我觉得应该是这个Also occurs if we try delete or update a row that does not exist.只不过not exist的是缓存。  如果缓存中没有 会查二级缓存 

此处跟缓存无关


3、Could not synchronize database state with session
Hibernate: delete from PA_THIRDLOG where streamNumber=?                                                                                                                                                                                                                                                                          
Hibernate: delete from PA_THIRDLOG where streamNumber=?                                                                                                                                                                                                                                                                          
ERROR  - Could not synchronize database state with session                                                                                                                                                                                                                                                                       
org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1     

Hibernate: delete from PA_THIRDLOG where streamNumber=?  是执行了两次 还是日志打印重复了? 
此处很明显sql执行了。 怀疑删除执行了两次。
2 楼 风云无浪 2012-09-27  
jinnianshilongnian 写道
我觉得这个异常出现的原因和内存回收有关系,在内存回收的时候。 跟垃圾回收无关,况且你拿着这个model的引用不可能回收。

StaleStateException异常描述:
public class StaleStateException
extends HibernateException
Thrown when a version number or timestamp check failed, indicating that the Session contained stale data (when using long transactions with versioning). Also occurs if we try delete or update a row that does not exist.

Note that this exception often indicates that the user failed to specify the correct unsaved-value strategy for a class!

能否贴出详细异常,需要看一下详细异常。


垃圾回收不就是内存回收么?回收的是hibernate的缓存,不是数据,这个是由于hibernate缓存的数据不一致造成。
这个异常的描述我也看了,我觉得应该是这个Also occurs if we try delete or update a row that does not exist.只不过not exist的是缓存。
Hibernate: delete from PA_THIRDLOG where streamNumber=?           
Hibernate: delete from PA_THIRDLOG where streamNumber=?          
ERROR  - Could not synchronize database state with session                
org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1         
    at org.hibernate.jdbc.Expectations$BasicExpectation.checkBatched(Expectations.java:61)       
    at org.hibernate.jdbc.Expectations$BasicExpectation.verifyOutcome(Expectations.java:46)    
    at org.hibernate.jdbc.NonBatchingBatcher.addToBatch(NonBatchingBatcher.java:24)                 
    at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:2525)     
    at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:2702)    
    at org.hibernate.action.EntityDeleteAction.execute(EntityDeleteAction.java:77)        
    at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:279)             
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263)       
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:172)       
    at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)       
    at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)                 
    at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)                               
    at org.springframework.orm.hibernate3.HibernateAccessor.flushIfNecessary(HibernateAccessor.java:390)          
    at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:420)           
    at org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:374)       
    at org.springframework.orm.hibernate3.HibernateTemplate.delete(HibernateTemplate.java:846)          
    at org.springframework.orm.hibernate3.HibernateTemplate.delete(HibernateTemplate.java:842) 
1 楼 jinnianshilongnian 2012-09-27  
我觉得这个异常出现的原因和内存回收有关系,在内存回收的时候。 跟垃圾回收无关,况且你拿着这个model的引用不可能回收。

StaleStateException异常描述:
public class StaleStateException
extends HibernateException
Thrown when a version number or timestamp check failed, indicating that the Session contained stale data (when using long transactions with versioning). Also occurs if we try delete or update a row that does not exist.

Note that this exception often indicates that the user failed to specify the correct unsaved-value strategy for a class!

能否贴出详细异常,需要看一下详细异常。

相关推荐

    Hibernate 调用存储过程

    如果存储过程返回多个结果集,Hibernate只会处理第一个结果集,其他结果集会被忽略。 2. **调用语法**:调用存储过程时,可以使用`{?=call selectAllUsers()}`或简化为`{call selectAllUsers()}`。 3. **非查询...

    关于struts2和hibernate的部分注解解释

    - **@JsonIgnore**:用于在进行JSON序列化时忽略特定属性。 - **@Id**:标记一个实体类中的主键字段。每个实体类只能有一个字段被标记为`@Id`。 - **@GeneratedValue**:用于指定主键的生成策略。 - **strategy*...

    hibernate入門

    ### hibernate入門 #### 知识点概览 本文档旨在为初学者提供一份全面且易懂的 Hibernate 学习指南。通过本教程的学习,读者可以了解到 Hibernate 的基本概念、工作原理及其在 Java 开发中的应用。主要内容涵盖 ...

    youcode_hibernate

    - CRUD操作:创建(Create)、读取(Read)、更新(Update)和删除(Delete)数据的方法。 - HQL(Hibernate Query Language):类似于SQL的查询语言,用于在对象层面进行查询。 - Criteria API:提供了一种动态构造...

    ***我的Oracle SQL总结!!!

    在Oracle SQL与Hibernate结合时,可能会涉及到HQL(Hibernate Query Language)和Criteria API,这些都是用于在Java应用中执行数据库查询的方式。 综上所述,这个博客可能探讨了Oracle SQL的基本语法、NULL处理、...

    使用JAVA实现高并发无锁数据库操作步骤分享

    在高并发的在线游戏中,传统的数据库操作方式,如直接使用Hibernate插入数据,往往无法满足性能需求。为了解决这个问题,我们可以采用无锁的数据库操作策略,通过Java实现。下面将详细介绍如何一步步实现这一目标。 ...

    缓存技术详解

    这意味着即使内存满载,也可以将数据存储在磁盘上,从而解决了容量问题。 5. **数据持久化**:缓存在虚拟机重启时会自动写入磁盘,确保数据安全。 6. **分布式缓存**:Ehcache支持通过RMI(Remote Method Invocation)...

    SSH当当网 使用struts2

    通过Hibernate的Session接口,开发者可以方便地执行CRUD(Create, Read, Update, Delete)操作,而无需编写大量的SQL语句。 在"SSH当当网"项目中,`mydang`这个压缩包文件很可能包含了整个项目的源代码和资源文件。...

    完整jersey包和jackson-all-1.9.2.jar

    6. **与其他框架集成**:Jackson可以轻松地与Spring、Hibernate等框架集成,实现JSON数据的自动转换。 **标签关联知识点** - **jersey与json**:Jersey通过集成Jackson库,提供了对JSON数据的支持。开发者可以通过...

    支持多数据库的ORM框架ef-orm.zip

    而本质上,当我们调用某H框架的session.get、session.load、session.delete时,我们是想传递一个以对象形式表达的数据库操作请求。只不过某H框架要求(并且限制)我们将其视作纯粹的“单个”对象而已。JPA 2.0为了...

    Gauss数据库权限识别项目.zip

    3. **权限(Privilege)**: 操作数据库的能力,如SELECT(读取数据)、INSERT(插入数据)、UPDATE(更新数据)、DELETE(删除数据)等。 4. **权限授予(Grant)**: 将权限赋予用户或角色的过程。 5. **权限撤销...

    Crud-Project-源码.rar

    Crud-Project-源码是一个关于CRUD操作的项目源代码,CRUD代表创建(Create)、读取(Retrieve)、更新(Update)和删除(Delete),这是数据库操作的基础。这个项目可能是一个用特定编程语言实现的示例,用于教学或者实践...

    Morphia一个nosql的ORM框架

    在传统的SQL世界里,ORM框架如Hibernate简化了与数据库的交互,而在NoSQL领域,Morphia扮演着相同的角色,使得开发者能够以面向对象的方式操作MongoDB数据,而无需直接编写低级的MongoDB查询语言。 **1. MongoDB和...

    基于MVC设计模式shop完整项目代码

    例如,可能会有一个`Product`模型类,包含`id`、`name`、`price`等属性,以及`save()`、`delete()`、`fetchAll()`等方法。模型层的职责是保持数据的一致性和有效性,确保业务规则得到正确执行。 **二、视图(View)...

    面试资料大全(宝典)

    它可以通过类的定义来实现,忽略掉不相关的细节,关注与当前问题最相关的特性。 - **继承**: 继承是一种强大的机制,它允许创建一个新类(子类)来继承现有类(父类)的属性和行为。这样可以在不重复编写相同代码的...

    基于javaweb的作业管理系统源码

    1. **src**:源代码目录,包括Java类文件,可能有controller(控制层)、service(业务逻辑层)、dao(数据访问层)和model(模型层)等不同层次的包结构。 2. **webapp**:Web应用资源目录,包括JSP页面、静态资源...

    实现了常用的数据库CRUD操作.zip

    在本项目中,我们主要关注的是利用SpringBoot框架实现数据库的CRUD(Create, Read, Update, Delete)操作。SpringBoot是Spring框架的一个简化版本,它旨在简化初始设置和配置,使得开发人员能够快速地创建独立的、...

    restFrameworkSimple:一个简单的休息框架

    在RESTful API中,Hibernate可能用于从数据库中检索或更新资源,确保数据的一致性和完整性。 Jersey是JAX-RS(Java API for RESTful Web Services)的参考实现,它为构建RESTful服务提供了便利。开发者可以通过注解...

    HibernateCreateProject

    这个项目可能包括设置项目结构、配置Hibernate、创建实体类、编写DAO(数据访问对象)层以及服务层代码等步骤。开发者通过这个项目可以深入理解如何将Java对象与数据库表进行映射,以及如何利用Hibernate简化数据库...

    项目的java后台源码

    3. **数据库连接与ORM**:项目可能使用JDBC进行数据库操作,或者利用Hibernate、MyBatis等ORM(对象关系映射)工具,将Java对象与数据库表对应,方便数据操作。 4. **RESTful API设计**:Java后台通常会提供RESTful...

Global site tag (gtag.js) - Google Analytics