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

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

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

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

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

 <?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class dynamic-update="true" name="entity.Dept" schema="ACCP" table="DEPT">
<id column="DEPTNO" name="deptNo" type="java.lang.String" length="20">
<generator class="assigned"></generator>
</id>
<property name="deptName" column="DEPTNAME" type="java.lang.String" />
<property name="location" column="LOCATION" type="java.lang.String" />
<set name="emps" cascade="all">
<key column="DEPTNO" />
<one-to-many class="entity.Emp"/>
</set>
</class>
</hibernate-mapping>

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

 package entity;

 import java.io.Serializable;

 public class Emp implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private String empNo;
private String empName;
private Dept dept; public Emp(){} public Emp(String empNo,String empName){
this.empNo = empNo;
this.empName = empName;
}
public String getEmpNo() {
return empNo;
}
public void setEmpNo(String empNo) {
this.empNo = empNo;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
} public Dept getDept() {
return dept;
} public void setDept(Dept dept) {
this.dept = dept;
} }
 package entity;

 import java.io.Serializable;
import java.util.HashSet;
import java.util.Set; public class Dept implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L; private String deptNo;
private String deptName;
private String location; private Set<Emp> emps = new HashSet<Emp>(); public Dept(){}
public Dept(String deptNo,String deptName,String location){
this.deptNo = deptNo;
this.deptName = deptName;
this.location = location;
}
public String getDeptNo() {
return deptNo;
}
public void setDeptNo(String deptNo) {
this.deptNo = deptNo;
}
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public Set<Emp> getEmps() {
return emps;
}
public void setEmps(Set<Emp> emps) {
this.emps = emps;
} }

4.测试类

下面只写出测试的方法,

 public void deleteDeptAndEmps(){
currentSession();
beginTransaction();
Dept dept = (Dept)session.load(Dept.class, "1001");
session.delete(dept);
commitTransaction();
closeSession();
}

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();
}
}

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

 org.hibernate.exception.GenericJDBCException: Could not execute JDBC batch update
at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:126)
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:114)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:266)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:169)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1028)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:366)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:137)
at util.HibernateUtil.commitTransaction(HibernateUtil.java:44)
at dao.impl.EmpDaoImpl.deleteDeptAndEmps(EmpDaoImpl.java:49)
at test.dao.EmpDaoImplTest.testDeleteDeptAndEmps(EmpDaoImplTest.java:21)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: java.sql.BatchUpdateException: ORA-01407: 无法更新 ("ACCP"."EMP"."DEPTNO") 为 NULL at oracle.jdbc.driver.DatabaseError.throwBatchUpdateException(DatabaseError.java:343)
at oracle.jdbc.driver.OraclePreparedStatement.executeBatch(OraclePreparedStatement.java:10720)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268)
... 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作为持久化工具在处理持久化删除时它的操作方式,是不是很有意思。有问题的话大家可以一起交流。

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

  1. 严重: Could not synchronize database state with session org.hibernate.exception.DataException: Could not execute JDBC batch update

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Monaco; color: #ff2600 } p.p2 { margin: 0.0px 0 ...

  2. Hibernate错误:Exception in thread "main" org.hibernate.exception.SQLGrammarException: Could not execute JDBC batch update

    报错:Exception in thread "main" org.hibernate.exception.SQLGrammarException: Could not execu ...

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

    没有什么问题,但是却报了Could not execute JDBC batch update的错,主要是配置文件设置了关联,数据却没有关联造成的,只要数据正确就没有问题. 另外,造成这个原因的还可能 ...

  4. Hibernate 抛出的 Could not execute JDBC batch update

    异常堆栈 org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update at or ...

  5. hibernate添加数据报错:Could not execute JDBC batch update

    报错如下图所示: 报错原因:在配置文件或注解里设置了字段关联,但数据却没有关联. 解决方法:我的错误是向一个多对多的关联表里插入数据,由于表中一个字段的数据是从另一张表里get到的,通过调试发现,从以 ...

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

    http://blog.csdn.net/derpvailzhangfan/article/details/2332795\ 上述问题: 一设置关联 二包含关键字 三 映射文件设置 catalog=“ ...

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

    MySQL中利用外键实现级联删除.更新 MySQL支持外键的存储引擎只有InnoDB,在创建外键的时候,要求父表必须有对应的索引,子表在创建外键的时候也会自动创建对应的索引.在创建索引的时候,可以指定 ...

  8. 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.h ...

  9. ERROR: Field 'PostId' doesn't have a default value Exception in thread "main" org.hibernate.exception.GenericJDBCException: could not execute statement

    例子: Post p = new Post(); p.setPostId(3); p.setPostName("技术"); 在执行数据保持时提示session.save(p); 的 ...

随机推荐

  1. jQuery对象是怎么创建的

    一.jQuery源码 在jQuery中,$是jQuery的别名,执行“$()”就是执行“jQuery()”,执行“$()”返回的是一个jQuery对象,在源码中,它是这样定义的: ... var jQ ...

  2. [bzoj 1025][SCOI2009]游戏(DP)

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1025 分析:首先这个问题等价于A1+A2+……Ak=n,求lcm(A1,A2,……,Ak)的种 ...

  3. 为什么Java使用System.getenv()获取刚刚设置的环境变量时为空

    场景: 在Ubuntu下已经启动了Eclipse,然后通过终端设置了环境变量(export $ENV=123),然后通过System.getenv()获取时显示为空. 解释: 环境变量仅在进程树下方, ...

  4. Ubuntu查看和写入系统日志

    一.背景 Linux将大量事件记录到磁盘上,它们大部分以纯文本形式存储在/var/log目录中.大多数日志条目通过系统日志守护进程syslogd,并被写入系统日志. Ubuntu包括以图形方式或从命令 ...

  5. dubbo bug之 Please check registry access list (whitelist/blacklist)的分析与解决

    1.基本就是dubbo provider没有启动会造成这种情况. 2.api和service是同一个项目,并不是俩项目. 通过启动api,run on server是不能启动service的,必须通过 ...

  6. DICOM:dcm4che工具包怎样压缩dcm文件探讨(续篇)

    背景 前段时间博文DICOM:dcm4che工具包怎样压缩dcm文件探讨(前篇)提到了一个问题:"利用dcm4che工具包中的dcm2dcm来进行dcm文件的压缩和加压缩.即改变dcm文件里 ...

  7. sgu101Domino

    给你一些边,假设存在欧拉路径就打出来 我的代码例如以下: #include<iostream> #include<cstring> using namespace std; i ...

  8. Js通用验证

    //-----------------------------------------------------js 验证封装 zhy2014-07-10------------------------ ...

  9. java学习总结——你的前世今生

    一.背景 JAVA语言最開始仅仅是Sun电脑(Sun MicroSystems)公司在1990年12月開始研究的一个内部项目. Sun电脑公司的一个叫做帕特里克·诺顿的project师被公司自己开发的 ...

  10. iOS开发-植入广告(iAd, Admob实例)

    应用中植入广告是一种非常好的盈利手段. 以下介绍主流的两种方法.iAd, Admob 先mark一个非常具体的pdf.   http://pan.baidu.com/share/link?sharei ...