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); 的 ...
随机推荐
- jQuery对象是怎么创建的
一.jQuery源码 在jQuery中,$是jQuery的别名,执行“$()”就是执行“jQuery()”,执行“$()”返回的是一个jQuery对象,在源码中,它是这样定义的: ... var jQ ...
- [bzoj 1025][SCOI2009]游戏(DP)
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1025 分析:首先这个问题等价于A1+A2+……Ak=n,求lcm(A1,A2,……,Ak)的种 ...
- 为什么Java使用System.getenv()获取刚刚设置的环境变量时为空
场景: 在Ubuntu下已经启动了Eclipse,然后通过终端设置了环境变量(export $ENV=123),然后通过System.getenv()获取时显示为空. 解释: 环境变量仅在进程树下方, ...
- Ubuntu查看和写入系统日志
一.背景 Linux将大量事件记录到磁盘上,它们大部分以纯文本形式存储在/var/log目录中.大多数日志条目通过系统日志守护进程syslogd,并被写入系统日志. Ubuntu包括以图形方式或从命令 ...
- dubbo bug之 Please check registry access list (whitelist/blacklist)的分析与解决
1.基本就是dubbo provider没有启动会造成这种情况. 2.api和service是同一个项目,并不是俩项目. 通过启动api,run on server是不能启动service的,必须通过 ...
- DICOM:dcm4che工具包怎样压缩dcm文件探讨(续篇)
背景 前段时间博文DICOM:dcm4che工具包怎样压缩dcm文件探讨(前篇)提到了一个问题:"利用dcm4che工具包中的dcm2dcm来进行dcm文件的压缩和加压缩.即改变dcm文件里 ...
- sgu101Domino
给你一些边,假设存在欧拉路径就打出来 我的代码例如以下: #include<iostream> #include<cstring> using namespace std; i ...
- Js通用验证
//-----------------------------------------------------js 验证封装 zhy2014-07-10------------------------ ...
- java学习总结——你的前世今生
一.背景 JAVA语言最開始仅仅是Sun电脑(Sun MicroSystems)公司在1990年12月開始研究的一个内部项目. Sun电脑公司的一个叫做帕特里克·诺顿的project师被公司自己开发的 ...
- iOS开发-植入广告(iAd, Admob实例)
应用中植入广告是一种非常好的盈利手段. 以下介绍主流的两种方法.iAd, Admob 先mark一个非常具体的pdf. http://pan.baidu.com/share/link?sharei ...