hibernate 級聯刪除報更新失敗的問題(org.hibernate.exception.GenericJDBCException: Could not execute JDBC batch up

首先hibernate級聯刪除的前提是,首先須要在映射文件中配置,配置多表之間的關聯關係:java

下面以部門表(Dept)和員工表(Emp)爲例:sql

1.在Emp.hbm.xml映射文件中配置many-to-one關係session

 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關係oracle

 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.編寫部門和員工的實體類app

 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.測試類eclipse

下面只寫出測試的方法,工具

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

運行的結果會出現下面錯誤:this

 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") 爲 NULLlua

這時爲何呢,咱們先看看執行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做爲持久化工具在處理持久化刪除時它的操做方式,是否是頗有意思。有問題的話你們能夠一塊兒交流。

相關文章
相關標籤/搜索