hibernate 级联删除报更新失败的问题(org.hibernate.exception.GenericJDBCException: Could not execute JDBC batch update)

首先hibernate级联删除的前提是,首先需要在映射文件中配置,配置多表之间的关联关系:

下面以部门表(Dept)和员工表(Emp)为例:

1.在Emp.hbm.xml映射文件中配置many-to-one关系

 1 <?xml version="1.0"?>
 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 3                                    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
 4 <hibernate-mapping>
 5  <class dynamic-update="true" name="entity.Emp" schema="ACCP" table="EMP">
 6   <id column="EMPNO" name="empNo" type="java.lang.String" length="20">
 7    <generator class="assigned"></generator>
 8   </id>
 9   <property name="empName" column="EMPNAME" type="java.lang.String" not-null="true"/>
10   <many-to-one name="dept" class="entity.Dept">
11       <column name="DEPTNO" />
12   </many-to-one>
13  </class>
14 </hibernate-mapping>

2.在Dept.hbm.xml映射文件中配置one-to-many关系

 1 <?xml version="1.0"?>
 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 3                                    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
 4 <hibernate-mapping>
 5  <class dynamic-update="true" name="entity.Dept" schema="ACCP" table="DEPT">
 6   <id column="DEPTNO" name="deptNo" type="java.lang.String" length="20">
 7    <generator class="assigned"></generator>
 8   </id>
 9   <property name="deptName" column="DEPTNAME" type="java.lang.String" />
10   <property name="location" column="LOCATION" type="java.lang.String"  />
11   <set name="emps" cascade="all">
12       <key column="DEPTNO" />
13       <one-to-many class="entity.Emp"/>
14   </set>
15  </class>
16 </hibernate-mapping>

3.编写部门和员工的实体类

 1 package entity;
 2
 3 import java.io.Serializable;
 4
 5 public class Emp implements Serializable{
 6     /**
 7      *
 8      */
 9     private static final long serialVersionUID = 1L;
10     private String empNo;
11     private String empName;
12     private Dept dept;
13
14     public Emp(){}
15
16     public Emp(String empNo,String empName){
17         this.empNo = empNo;
18         this.empName = empName;
19     }
20     public String getEmpNo() {
21         return empNo;
22     }
23     public void setEmpNo(String empNo) {
24         this.empNo = empNo;
25     }
26     public String getEmpName() {
27         return empName;
28     }
29     public void setEmpName(String empName) {
30         this.empName = empName;
31     }
32
33     public Dept getDept() {
34         return dept;
35     }
36
37     public void setDept(Dept dept) {
38         this.dept = dept;
39     }
40
41 }
 1 package entity;
 2
 3 import java.io.Serializable;
 4 import java.util.HashSet;
 5 import java.util.Set;
 6
 7 public class Dept implements Serializable{
 8     /**
 9      *
10      */
11     private static final long serialVersionUID = 1L;
12
13     private String deptNo;
14     private String deptName;
15     private String location;
16
17     private Set<Emp> emps = new HashSet<Emp>();
18
19     public Dept(){}
20     public Dept(String deptNo,String deptName,String location){
21         this.deptNo = deptNo;
22         this.deptName = deptName;
23         this.location = location;
24     }
25     public String getDeptNo() {
26         return deptNo;
27     }
28     public void setDeptNo(String deptNo) {
29         this.deptNo = deptNo;
30     }
31     public String getDeptName() {
32         return deptName;
33     }
34     public void setDeptName(String deptName) {
35         this.deptName = deptName;
36     }
37     public String getLocation() {
38         return location;
39     }
40     public void setLocation(String location) {
41         this.location = location;
42     }
43     public Set<Emp> getEmps() {
44         return emps;
45     }
46     public void setEmps(Set<Emp> emps) {
47         this.emps = emps;
48     }
49
50
51 }

4.测试类

下面只写出测试的方法,

1 public void deleteDeptAndEmps(){
2         currentSession();
3         beginTransaction();
4         Dept dept = (Dept)session.load(Dept.class, "1001");
5         session.delete(dept);
6         commitTransaction();
7         closeSession();
8 }

5.进行测试

package test.dao;

import static org.junit.Assert.*;

import org.junit.Ignore;
import org.junit.Test;

import dao.impl.EmpDaoImpl;

public class EmpDaoImplTest extends EmpDaoImpl{
    @Test
    public void testDeleteDeptAndEmps(){
        deleteDeptAndEmps();
    }
}

运行的结果会出现下面错误:

 1 org.hibernate.exception.GenericJDBCException: Could not execute JDBC batch update
 2     at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:126)
 3     at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:114)
 4     at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
 5     at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275)
 6     at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:266)
 7     at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:169)
 8     at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
 9     at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
10     at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1028)
11     at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:366)
12     at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:137)
13     at util.HibernateUtil.commitTransaction(HibernateUtil.java:44)
14     at dao.impl.EmpDaoImpl.deleteDeptAndEmps(EmpDaoImpl.java:49)
15     at test.dao.EmpDaoImplTest.testDeleteDeptAndEmps(EmpDaoImplTest.java:21)
16     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
17     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
18     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
19     at java.lang.reflect.Method.invoke(Method.java:597)
20     at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
21     at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
22     at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
23     at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
24     at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
25     at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
26     at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
27     at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
28     at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
29     at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
30     at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
31     at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
32     at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
33     at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
34     at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
35     at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
36     at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
37     at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
38     at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
39 Caused by: java.sql.BatchUpdateException: ORA-01407: 无法更新 ("ACCP"."EMP"."DEPTNO") 为 NULL
40
41     at oracle.jdbc.driver.DatabaseError.throwBatchUpdateException(DatabaseError.java:343)
42     at oracle.jdbc.driver.OraclePreparedStatement.executeBatch(OraclePreparedStatement.java:10720)
43     at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70)
44     at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268)
45     ... 33 more

重点关注这一条错误:无法更新 ("ACCP"."EMP"."DEPTNO") 为 NULL

这时为什么呢,我们先看看执行hibernate删除时的sql语句:

Hibernate:
    select
        dept0_.DEPTNO as DEPTNO4_0_,
        dept0_.DEPTNAME as DEPTNAME4_0_,
        dept0_.LOCATION as LOCATION4_0_
    from
        ACCP.DEPT dept0_
    where
        dept0_.DEPTNO=?
Hibernate:
    select
        emps0_.DEPTNO as DEPTNO1_,
        emps0_.EMPNO as EMPNO1_,
        emps0_.EMPNO as EMPNO5_0_,
        emps0_.EMPNAME as EMPNAME5_0_,
        emps0_.DEPTNO as DEPTNO5_0_
    from
        ACCP.EMP emps0_
    where
        emps0_.DEPTNO=?
Hibernate:
    update
        ACCP.EMP
    set
        DEPTNO=null
    where
        DEPTNO=?

从上面我们可以看出,要执行级联删除,要删除Dept表中部门的同时删除Emp表对于部门下的所有员工信息,hibernate是这么干的:

(1)hibernate首先会查询出对应要删除的部门信息

(2)然后级联查询出对于的部门下的所有员工信息

(3)接着更新对于部门下的所有员工,将其部门更新为null

好,问题出现了,报错就在这一个步骤,既然要更新为null,那么Emp表在设计时就要能够让Emp表中的deptNo这个字段能够为null,也就是可以为空,下面就将正确的表

设计显示如下:

好了,上面的勾打上了,那么问题就解决了。

下面我们再执行一次级联删除的方法,看看最终效果:

对于的sql语句情况如下:

Hibernate:
    select
        dept0_.DEPTNO as DEPTNO4_0_,
        dept0_.DEPTNAME as DEPTNAME4_0_,
        dept0_.LOCATION as LOCATION4_0_
    from
        ACCP.DEPT dept0_
    where
        dept0_.DEPTNO=?
Hibernate:
    select
        emps0_.DEPTNO as DEPTNO1_,
        emps0_.EMPNO as EMPNO1_,
        emps0_.EMPNO as EMPNO5_0_,
        emps0_.EMPNAME as EMPNAME5_0_,
        emps0_.DEPTNO as DEPTNO5_0_
    from
        ACCP.EMP emps0_
    where
        emps0_.DEPTNO=?
Hibernate:  ---------------------------------------------〈〈〈〈看该句下面的变化
    update
        ACCP.EMP
    set
        DEPTNO=null
    where
        DEPTNO=?
Hibernate:
    delete
    from
        ACCP.EMP
    where
        EMPNO=?
Hibernate:
    delete
    from
        ACCP.DEPT
    where
        DEPTNO=?

从上面可以得出hibernate执行级联删除的步骤分为5步:

(1)同上

(2)同上

(3)同上

(4)删除Emp表中对应部门的所有信息记录

(5)最后删除Dept表中对应得部门信息

OK,问题解决,通过这个级联删除,使我们能够更加充分的认识hibernate作为持久化工具在处理持久化删除时它的操作方式,是不是很有意思。有问题的话大家可以一起交流。

时间: 2024-08-10 17:09:07

hibernate 级联删除报更新失败的问题(org.hibernate.exception.GenericJDBCException: Could not execute JDBC batch update)的相关文章

org.hibernate.exception.SQLGrammarException: Could not execute JDBC batch update

org.hibernate.exception.SQLGrammarException: Could not execute JDBC batch update org.hibernate.exception.SQLGrammarException: Could not execute JDBC batch update,码迷,mamicode.com org.hibernate.exception.SQLGrammarException: Could not execute JDBC batc

exception is org.hibernate.exception.DataException: Could not execute JDBC batch update at

没有什么问题,但是却报了Could not execute JDBC batch update的错,主要是配置文件设置了关联,数据却没有关联造成的,只要数据正确就没有问题. 另外,造成这个原因的还可能是数据库的驱动jar包不支持. 还有就是csdn的dizhang的专栏提到的下面问题引起的: 1.因为Hibernate Tools(或者Eclipse本身的Database Explorer)生成*.hbn.xml工具中包含有catalog="***"(*表示数据库名称)这样的属性,将该

Hibernate 抛出的 Could not execute JDBC batch update

异常堆栈 org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:94) at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.

sping异常记录----Could not execute JDBC batch update; nested exception is org.hibernate.excepti

今天在练习如何SSH中进行单元测试的时候出现下列异常: org.springframework.dao.DataIntegrityViolationException: Could not execute JDBC batch update; nested exception is org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update at org.springframe

hibernate的Could not execute JDBC batch update错误原因及处理

http://blog.csdn.net/derpvailzhangfan/article/details/2332795\ 上述问题: 一设置关联 二包含关键字 三 映射文件设置 catalog="" 都不能解决我的问题,最大的可能是 四 数据库中的jar包不支持批量操作. 这次很不严谨的不去实验,数据能够正确的操作到数据库中,好困.....

关于数据的级联删除和更新

两张表:“ProductCategory”,“Product”. 有一个需求是这样的:在删除某个ProductCategory 的时候,同时删除该Category的products. 在MySQL中利用外键实现级联删除 创建以下测试用数据库表: CREATE TABLE `roottb` ( `id` INT(11) UNSIGNED AUTO_INCREMENT NOT NULL, `data` VARCHAR(100) NOT NULL DEFAULT '', PRIMARY KEY (`i

hibernate级联保存,更新个人遇到的问题

在级联更新的时候,数据库中的数据是增加的,只是外键不存在,导致这样的问题产生的原因是,字表主键ID没有添加到集合中,导致Hibernate找不到子项而执行更新. hibernate级联保存,更新个人遇到的问题,布布扣,bubuko.com

[原创]MYSQL中利用外键实现级联删除和更新

MySQL中利用外键实现级联删除.更新 MySQL支持外键的存储引擎只有InnoDB,在创建外键的时候,要求父表必须有对应的索引,子表在创建外键的时候也会自动创建对应的索引.在创建索引的时候,可以指定在删除.更新父表时,对子表进行的相应操作,包括RESTRICT.NO ACTION.SET NULL和CASCADE.其中RESTRICT和NO ACTION相同,是指在子表有关联记录的情况下父表不能更新:CASCADE表示父表在更新或者删除时,更新或者删除子表对应记录:SET NULL则是表示父表

HTTP Status 500 - Request processing failed; nested exception is org.hibernate.exception.GenericJDBCException: could not execute statement

1.什么操作出现:当我在项目中添加产品或者修改时,浏览器出现HTTP Status 500 - Request processing failed; nested exception is org.hibernate.exception.GenericJDBCException: could not execute statement; Ecplise出现这个: 十二月 20, 2017 1:51:02 下午 org.apache.catalina.core.StandardWrapperVal