最近在做项目的时候遇到一个问题,客户在使用Hibernate往数据库插入记录时总是遇到这样的错误信息:
Caused by: net.sf.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
at net.sf.hibernate.exception.ErrorCodeConverter.convert(ErrorCodeConverter.java:73)
at net.sf.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:29)
at net.sf.hibernate.impl.BatcherImpl.convert(BatcherImpl.java:328)
at net.sf.hibernate.impl.BatcherImpl.executeBatch(BatcherImpl.java:135)
at net.sf.hibernate.impl.SessionImpl.executeAll(SessionImpl.java:2438)
at net.sf.hibernate.impl.SessionImpl.execute(SessionImpl.java:2396)
at net.sf.hibernate.impl.SessionImpl.flush(SessionImpl.java:2261)
... 3 more
Caused by: java.sql.BatchUpdateException: Duplicate entry '42808-0' for key 1
at com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:894)
at org.apache.commons.dbcp.DelegatingStatement.executeBatch(DelegatingStatement.java:294)
at net.sf.hibernate.impl.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:54)
at net.sf.hibernate.impl.BatcherImpl.executeBatch(BatcherImpl.java:128)
... 7 more
而这个问题在本地测试时并未出现,开始时猜测是客户的数据库结构与本地的数据库结构不同造成的,可是经过比对,客户的数据库结构和环境与本地完全一样。
接下来分析数据库中的数据库中的数据,发现在几个表中存在垃圾数据。为了说明情况,我们假定A表中有垃圾数据,A与B、C表通过外键关联(用的是MySQL4.0,我自己不太了解,似乎没有5.0来的那么严格),然而,有意思的是在B、C表中并没有相关的数据,而且A中相关记录的PK明显大于B、C表中的最大PK。
由于B、C两个表的主键由Hibernate生成,采用的生成机制是identity,因此,主键的生成实际上是依赖于MySQL数据库本身。对于MySQL而言,数据库本身会维护本身的index,如果数据库的当前的最大的index是2000,即使删除了后一千条数据,新生成的数据也应该从2001开始。反过来,既然在A表中存在大于B、C表中最大PK的记录,那么说明A中这些个对应记录的至少曾经在B、C表存在过,那么在重新生成时,不应该出现重复的记录出现才对啊!
继续检查代码,发现A表是在B、C生成的时候自动生成的,但是删除的时候却忘了删除,但是即使这样,也不该出现先前提到的情况啊!
询问客户的数据库的情况,才知道,客户的数据库是新装了之后用以前的SQL备份文件恢复的!这下终于找到症结了,使用SQL恢复时并将相应表的Index生成记录也恢复,以至于垃圾数据与现有的新生成的数据冲突了!
二话不说,先删除垃圾数据,本来想一条SQL搞定的,无奈4.0不支持增量查询,delete的where字句也不能使用in\not in作为谓词,晕,写程序吧,经过一个小时左右,各个功能搞定!OK
后来想起来,这个问题在平常使用时经常存在,总结一下吧:
- 级联删除要正确的配置
- 数据库的备份SQL慎用,尤其是在与数据库本身主键生成相关的项目。
- 数据库的数据一致性很重要
分享到:
相关推荐
在使用 Hibernate 进行持久化操作时,经常需要处理实体类的主键问题。Hibernate 提供了多种主键生成策略,每种策略都有其特定的应用场景和优缺点。 #### 二、详细解释 接下来,我们将详细介绍给定文件中提到的几种...
对于 MySQL 和 SQL Server,则使用 identity(自增主键生成机制)。这种方法非常灵活,通常推荐使用。 - **应用场景**:适用于多种数据库环境,尤其是当项目可能跨越不同类型的数据库时。 #### 2. Assigned - **...
### Hibernate主键生成策略 #### 一、概述 在Hibernate框架中,主键生成策略是对象持久化过程中不可或缺的一部分。合理的主键生成机制不仅能够确保数据的唯一性,还能够提高系统的性能和可扩展性。本文将详细介绍...
这些工具能够解析Java源代码,从中提取实体类信息并生成相应的SQL语句。 4. **MyBatis Generator**: MyBatis Generator是一个强大的工具,可以自动生成Java实体类、Mapper接口、Mapper XML文件以及建表语句。只需...
本文主要介绍在使用Hibernate框架时,如何针对不同的数据库(如SQL Server和MySQL)进行配置,并实现XML映射语句的编写。 #### 二、Hibernate配置详解 ##### 2.1 MySQL配置 在Hibernate中,配置MySQL作为数据源...
Hibernate是一款强大的对象关系映射(ORM)框架,它允许开发者用Java对象来操作数据库,而无需直接编写SQL语句。关系映射XML生成工具,如"Middlegen-Hibernate-r5",则是为了简化这一过程而设计的。这些工具能够自动...
在MySQL中,你可以通过SQL语句创建表,或者使用可视化工具如phpMyAdmin来创建。 接着,新建一个myEclipse项目,并将其转换为Hibernate项目。在项目属性设置中,配置Hibernate的相关信息,包括JDBC驱动、数据库URL、...
在这个场景中,异常的根因是嵌套的“org.hibernate.exception.SQLGrammarException: could not execute query”,这是Hibernate在处理SQL语句时抛出的异常,通常与SQL语法错误或表结构不匹配有关。当从SQL Server...
以下是对Hibernate主键类型及其配置的详细说明: 1. **uuid.hex**: 这种生成器使用128位算法生成一个32位的字符串。由于其通用性,它适用于所有类型的数据库。在`.hbm.xml`映射文件中,你可以这样配置: ```xml ...
通过JPA,开发者可以使用面向对象的方式来处理数据库操作,而不是直接编写SQL语句。 2. **实体(Entity)**: 在JPA中,实体类是Java对象,它们代表数据库表中的记录。通过在类上使用`@Entity`注解,JPA知道这个类是...
在Java开发中,Hibernate是一个非常流行的对象关系映射(ORM)框架,它允许开发者使用面向对象的方式处理数据库操作。在本教程中,我们将探讨如何利用Hibernate的注解功能,通过实体类自动生成数据库中的表。这极大...
在IT行业中,数据库管理和持久化...这使得我们能够方便快捷地进行数据库操作,而无需手动编写大量的SQL语句。在实际开发中,这种方式极大地提高了开发效率,降低了出错的可能性,也使得代码更具有可读性和可维护性。
使用 Hibernate 可以使用 saveOrUpdate 方法,但是使用原生 SQL 语句时,该如何实现 save 操作呢?今天,我们将讨论 MySQL 中 save 的写法汇总。 使用 IGNORE 关键字实现数据不存在则插入,存在则无操作 在 MySQL ...
本压缩包包含了使用Hibernate与MySQL数据库交互所需的jar包,这些库文件是搭建 Hibernate 应用的基础。下面我们将详细探讨Hibernate ORM框架以及与MySQL数据库的整合。 首先,Hibernate的核心功能是将Java类映射到...
通过提供对象-关系映射,Hibernate允许开发者将数据库操作转换为对Java对象的操作,从而减少了编写SQL语句的工作量。 ### 2. 为什么选择UUID作为主键 - **全局唯一性**:UUID生成的键值在全世界范围内都是唯一的,...
这些注解可以帮助JPA provider(例如Hibernate)生成对应的数据库表结构和SQL语句。 三、Hibernate概述 Hibernate是一个基于JPA规范的ORM(Object-Relational Mapping)框架,它提供了对数据库的访问和操作功能。...
本主题主要讲解如何利用工具或自定义脚本将MySQL数据表自动生成对应的Java实体类,提高开发效率。 首先,我们需要理解Java实体类的基本概念。在Java世界中,实体类通常用于ORM(对象关系映射)框架,如Hibernate或...
- 当应用启动时,Hibernate会读取配置,扫描实体类,然后根据元数据生成相应的SQL语句,执行这些语句以创建数据库表。 6. **注意事项**: - 数据库表的命名策略可以通过`@Table(name = "table_name")`自定义,...