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); 的 ...
随机推荐
- [luoguP2983] [USACO10FEB]购买巧克力Chocolate Buying(贪心)
传送门 按价格排序后贪心 ——代码 #include <cstdio> #include <iostream> #include <algorithm> int n ...
- poj 3925 枚举+prime
/* 因为15很小可以暴力枚举然后用最小生成树的prim来计算 */ #include<stdio.h> #include<string.h> #include<math ...
- [K/3Cloud]在插件中根据条件取消表单打开过程
新建一个类,继承自动态表单抽象插件类AbstractBillPlugIn,重写PreOpenForm. /// <summary> /// 销售订单 单据维护界面插件 /// </s ...
- 矩形面积求并(codevs 3044)
题目描述 Description 输入n个矩形,求他们总共占地面积(也就是求一下面积的并) 输入描述 Input Description 可能有多组数据,读到n=0为止(不超过15组) 每组数据第一行 ...
- [bzoj1115][POI2009]石子游戏Kam_博弈论_阶梯博弈
石子游戏 Kam bzoj-1115 POI-2009 题目大意:给定n堆石子,两个人轮流取石子.每堆石子的个数都不少于前一堆石子.每次取后也必须维持这个性质.问谁有必胜策略. 注释:$1\le ca ...
- cogs—— 310. [POJ2395] Out of Hay
310. [POJ2395] Out of Hay ★☆ 输入文件:outofhay.in 输出文件:outofhay.out 简单对比 时间限制:1 s 内存限制:128 MB De ...
- Android Studio Module 的添加与删除
1. 添加Module(此时可以字面翻译为“模块”,意译为“其他工程”) 2. 删除Module 你要知道,Android Studio的非人性设计,导致删除一个module都是繁琐的. 当你想在An ...
- ubuntu各文件夹简介 [转载]
原文地址:ubuntu各文件夹简介作者:SuperZhy ubuntu各文件夹简介 /bin 二进制可执行命令/dev 设备文件(硬盘/光驱等)/etc 系统管理和配置文件/etc/rc.d 启动的配 ...
- ubuntu Shell
Ubuntu下的ShellUbuntu的图形界面也是运行在Shell下的:虚拟终端机开启:Ctrl+Alt+F1~ F6 可以开启6个命令行的ShellCtrl+Alt+F7 开启图形终端机命令su ...
- Java课程设计——人事管理系统
主界面代码: package PersonSystem; import java.awt.*; import java.awt.event.*; import javax.swing.*; impor ...