hibernate 级联删除报更新失败的问题(org.hibernate.exception.GenericJDBCException: Could not execute JDBC batch update)
首先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)的更多相关文章
- 严重: 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 ...
- 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 ...
- exception is org.hibernate.exception.DataException: Could not execute JDBC batch update at
没有什么问题,但是却报了Could not execute JDBC batch update的错,主要是配置文件设置了关联,数据却没有关联造成的,只要数据正确就没有问题. 另外,造成这个原因的还可能 ...
- Hibernate 抛出的 Could not execute JDBC batch update
异常堆栈 org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update at or ...
- hibernate添加数据报错:Could not execute JDBC batch update
报错如下图所示: 报错原因:在配置文件或注解里设置了字段关联,但数据却没有关联. 解决方法:我的错误是向一个多对多的关联表里插入数据,由于表中一个字段的数据是从另一张表里get到的,通过调试发现,从以 ...
- hibernate的Could not execute JDBC batch update错误原因及处理
http://blog.csdn.net/derpvailzhangfan/article/details/2332795\ 上述问题: 一设置关联 二包含关键字 三 映射文件设置 catalog=“ ...
- [原创]MYSQL中利用外键实现级联删除和更新
MySQL中利用外键实现级联删除.更新 MySQL支持外键的存储引擎只有InnoDB,在创建外键的时候,要求父表必须有对应的索引,子表在创建外键的时候也会自动创建对应的索引.在创建索引的时候,可以指定 ...
- 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 ...
- 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); 的 ...
随机推荐
- Oracle怎么用(常用工具)
Oracle数据库管理系统装好了!那要怎么用呢? 将介绍的工具:①Database Configuration Assistant ②SQL Plus ③SQL Developer 一.Dat ...
- 洛谷 P2853 [USACO06DEC]牛的野餐Cow Picnic
P2853 [USACO06DEC]牛的野餐Cow Picnic 题目描述 The cows are having a picnic! Each of Farmer John's K (1 ≤ K ≤ ...
- Domino V8 在 UNIX/Linux 平台上的安装及其常见问题
在 IBM Bluemix 云平台上开发并部署您的下一个应用. 开始您的试用 Domino V8 的安装需求 Domino V8 可以支持多种平台和操作系统,表1 列出了其支持的各种 UNIX/Lin ...
- Chrome浏览器扩展开发系列之十四:本地消息机制Native messagin
Chrome浏览器扩展开发系列之十四:本地消息机制Native messaging 2016-11-24 09:36 114人阅读 评论(0) 收藏 举报 分类: PPAPI(27) 通过将浏览器 ...
- hdu 5416 CRB and Tree(2015 Multi-University Training Contest 10)
CRB and Tree Time Limit: 8000/4000 MS (J ...
- 在oracle中操作表及字段注释,查询一个表的所有字段名以及属性和约束
1.查询表注释 SELECT * FROM USER_TAB_COMMENTS; 三列:TABLE_NAME,TABLE_TYPE,COMMENTS 2.查询字段注释 SELECT * FROM US ...
- GPS时间
GPS信息里面包含一个时间戳. phonegap(即cordova)的地理位置API Geolocation 提供了对设备GPS传感器的访问,返回的数据中,除了坐标,还有一个时间戳timestamp. ...
- c++ 编译器会绕过拷贝构造函数
C++ primer P442 P447:在拷贝初始化过程中,编译器可以跳过拷贝构造函数,直接创建对象.即,编译器允许将下面的代码 "; //1 改写为 "); //2 由于str ...
- Bing Maps进阶系列四:路由功能服务(RouteService)
Bing Maps进阶系列四:路由功能服务(RouteService) Bing Maps提供的路由功能服务(RouteService)可以实现多方位的计算地图上的路线指示,路径行程等功能,比如说实现 ...
- java网络编程TCP
图片来自网络 [服务端] import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; im ...