Trouble Shooting on Hibernate StaleObjectStateException

本文探讨了在使用Grails 1.3.7时遇到的StaleObjectStateException问题,并详细介绍了如何通过调整Hibernate配置来解决该问题。通过提供一个实际的Java代码示例,演示了如何在不同乐观锁策略下重现和解决该异常。
Trouble Shooting on Hibernate StaleObjectStateException

I am getting StaleObjectStateException on grails 1.3.7.
Stale Object State Exception
Error Message
2013-03-05 16:26:06,140 [http-bio-8080-exec-35] ERROR com.sillycat.xxx.ErrorController - Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.sillycat.xxx.Device#3015]
org.codehaus.groovy.grails.web.errors.GrailsWrappedRuntimeException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.sillycat.xxx.Device#3015]
at Skipped non-sillycat elements.(:86)
Caused by: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [com.sillycat.xxx.Device#3015]
at Skipped non-sillycat elements.(:1)
at com.sillycat.xxxx.events.EventService.saveEvent(EventService.groovy:93)
at com.sillycat.xxx.events.GeoFenceEntryEventService.super$2$saveEvent(GeoFenceEntryEventService.groovy)
at Skipped non-sillycat elements.(:1)

Since the bottom of grails 1.3.7 is hibernate 3.3.1.GA. I begin to create the environment of Hibernate and I try to produce and solve that problem on Hibernate first.

1. Build the Hibernate environment
Packages Here is my pom.xml to fetch all the related packages
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-annotations</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.5.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.5.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.14</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.23</version>
</dependency>

And the version of Hibernate I am using is <hibernate.version>3.3.1.GA</hibernate.version>

Hibernate Configuration - hibernate.cfg.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Database connection settings -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost/test</property>
<property name="connection.username">root</property>
<property name="connection.password">kaishi</property>

<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">1</property>

<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>

<!-- Enable Hibernate's automatic session context management -->
<property name="current_session_context_class">thread</property>

<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>

<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>

<!-- Drop and re-create the database schema on startup -->
<property name="hbm2ddl.auto">update</property>

<!-- Mapping files -->
<mapping resource="hbm/student.hbm.xml" />

</session-factory>
</hibernate-configuration>

And the Object Configuration file for Hibernate
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
<!--
<class name="com.sillycat.easyhibernate.model.Student" table="students" optimistic-lock="all" dynamic-update="true">
<class name="com.sillycat.easyhibernate.model.Student" table="students" optimistic-lock="none">
-->
<class name="com.sillycat.easyhibernate.model.Student" table="students" optimistic-lock="none">
<id name="id" type="int" column="id">
<generator class="native" />
</id>
<property name="firstName">
<column name="first_name" />
</property>
<property name="lastName">
<column name="last_name" />
</property>
</class>
</hibernate-mapping>

2. Reproduce the Exception with Java Codes
package com.sillycat.easyhibernate.temp;

import java.util.Date;

import org.hibernate.Session;

import com.sillycat.easyhibernate.model.Student;
import com.sillycat.easyhibernate.util.HibernateUtil;

public class MyRunnable implements Runnable {
private String id;

@Override
public void run() {
Session session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
Student student = (Student) session.load(Student.class, Integer.valueOf(id));
student.setFirstName("xxx" + (new Date()).getTime());
session.save(student);
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
session.getTransaction().commit();
System.out.println("Done " + student.getFirstName());
}

public MyRunnable(String id) {
this.id = id;
}

}

package com.sillycat.easyhibernate.temp;


public class StaleObjectStateExceptionMain {


publicstaticvoid main(String[] args) {
for(int i = 0;i< 2;i++){
Thread t = new Thread(new MyRunnable("1"));
t.start();
}
}


}

If I am using the lock on hibernate configuration, the Exception will reproduce.
If I change it to none, it will work fine. So the most import part is as follow:
<class name="com.sillycat.easyhibernate.model.Student" table="students" optimistic-lock="all" dynamic-update="true">
<class name="com.sillycat.easyhibernate.model.Student" table="students" optimistic-lock="none">

References:
http://stackoverflow.com/questions/7664768/optimistic-locking-and-org-hibernate-staleobjectstateexception
http://www.grails.org/doc/1.3.7/guide/15.%20Grails%20and%20Hibernate.html
http://stackoverflow.com/questions/8081413/hibernate-program-errors


http://grails.org/doc/1.3.7/guide/single.html#5.5.2.7%20Optimistic%20Locking%20and%20Versioning
故障排除(Troubleshooting)是一种系统性的方法,旨在识别、诊断和解决系统、设备或应用程序中出现的问题或故障,这些问题可能导致系统无法正常工作、性能下降或其他不良影响。该过程涉及收集信息、分析数据、测试假设,并最终确定并实施解决方案,通常需要技术专业知识和经验,可能涉及多个领域,包括硬件、软件、网络、安全等。通过故障排除,可以及时解决问题,确保系统持续稳定运行[^2]。 在不同场景下,故障排除有不同的重点和方法: - **Linux系统**:解决常见的故障排错,需先了解系统的启动流程。在实际生产环境中,系统和数据基本安装在不同硬盘上,因为数据丢失会给企业带来损失,若系统和数据在同一硬盘,系统崩溃则无法获取数据。遇到故障时,不应首先考虑重装系统[^1]。同时,Linux下快速故障探测会涉及一些概念,如进程的user、PID、%CPU、%MEM、VSZ、RSS、TTY、STAT、START、TIME、COMMAND等信息[^4]。 - **程序员提升能力方面**:程序员可通过多种方式提高故障排除能力,如建立扎实的基础知识,拥有良好的编程基础和对计算机系统、数据结构、算法以及编程语言的深入理解,有助于快速定位问题;学会使用调试工具,熟练掌握各种调试工具,如IDE的调试功能、浏览器的开发者工具、日志分析工具等,可以更高效地找到问题;学习问题解决策略,熟悉常用的问题解决策略,如分治法、逐步细化、自上而下等,能有条不紊地解决问题;保持好奇心和耐心,遇到问题时保持好奇心,善于发现问题的规律,同时耐心分析问题,逐步缩小问题范围;优化代码阅读能力,多阅读别人的代码,有助于理解代码逻辑,从而更容易找到问题所在;学会提问和求助,遇到问题时向同事或网络社区提问,明确问题的关键点,同时从别人的问题和解决方案中汲取经验;复盘总结经验,每次解决问题后进行复盘,总结问题的原因、解决方法和改进方案;模拟故障排除场景,在空闲时间模拟常见的故障排除场景,提高应对问题的能力;深入了解业务,了解业务逻辑和需求,从用户角度看待问题,更容易找到问题所在;持续学习和进步,不断学习新技术、新方法,关注业界动态,参加技术研讨会、线上技术社区等,与其他程序员互动,共同提高[^3]。 - **网络方面**:以突然无法访问某些内部网站为例,可尝试使用`ipconfig /all`、`ipconfig/flushdns`、`ipconfig/release`、`ipconfig/release6 (ip6)`、`ipconfig/renew`、`ipconfig/renew6 (ip6)`等命令,若重启后仍无法解决,发现是DNS Suffix Search List缺失大部分站点,可通过控制面板中的网络连接,右键点击“Ethernet”,选择属性来解决问题[^5]。 ```python # 示例代码:简单的异常处理,模拟故障排除思路 try: num1 = int(input("请输入第一个数字: ")) num2 = int(input("请输入第二个数字: ")) result = num1 / num2 print(f"结果是: {result}") except ValueError: print("输入的不是有效的数字,请输入整数。") except ZeroDivisionError: print("除数不能为零。") ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值