Hibernate双向一对多级联添加

来源:互联网 发布:数控车床编程教程 编辑:程序博客网 时间:2024/05/03 17:24
 本例以Hibernate,Spring集成测试,以Oracle为数据库,以管理“部门---->员工”为例

 Oracle数据表如下:

 

--部门表create table t_dept( d_id number primary key, d_name varchar2(20) not null, d_remark varchar2(100) not null);--创建部门表的序列create sequence dept_seqstart with 1increment by 1;--员工表create table t_emp( e_id number primary key, d_id number references t_dept(d_id) not null, e_name varchar2(20) not null, e_sex varchar(4) not null);--创建员工表的序列create sequence emp_seqstart with 100increment by 1;--测试数据insert into t_dept values(dept_seq.nextval,'开发一部','it is good');insert into t_dept values(dept_seq.nextval,'开发二部','it is bad');insert into t_emp values(emp_seq.nextval,1,'张三','男');insert into t_emp values(emp_seq.nextval,1,'李四','男');insert into t_emp values(emp_seq.nextval,2,'王五','男');insert into t_emp values(emp_seq.nextval,2,'赵六','男');


 

 

生成的实体类如下:

TDept.java

package com.svse.entity;import java.util.HashSet;import java.util.Set;/** * TDept entity. *  * @author MyEclipse Persistence Tools */public class TDept implements java.io.Serializable { // Fields private Long DId; private String DName; private String DRemark; private Set TEmps = new HashSet(0); // Constructors /** default constructor */ public TDept() { } /** minimal constructor */ public TDept(String DName, String DRemark) {  this.DName = DName;  this.DRemark = DRemark; } /** full constructor */ public TDept(String DName, String DRemark, Set TEmps) {  this.DName = DName;  this.DRemark = DRemark;  this.TEmps = TEmps; } // Property accessors public Long getDId() {  return this.DId; } public void setDId(Long DId) {  this.DId = DId; } public String getDName() {  return this.DName; } public void setDName(String DName) {  this.DName = DName; } public String getDRemark() {  return this.DRemark; } public void setDRemark(String DRemark) {  this.DRemark = DRemark; } public Set getTEmps() {  return this.TEmps; } public void setTEmps(Set TEmps) {  this.TEmps = TEmps; }}

 

TEmp.java

package com.svse.entity;/** * TEmp entity. *  * @author MyEclipse Persistence Tools */public class TEmp implements java.io.Serializable { // Fields private Long EId; private TDept TDept=new TDept(); private String EName; // Constructors /** default constructor */ public TEmp() { } /** full constructor */ public TEmp(TDept TDept, String EName) {  this.TDept = TDept;  this.EName = EName; } // Property accessors public Long getEId() {  return this.EId; } public void setEId(Long EId) {  this.EId = EId; } public TDept getTDept() {  return this.TDept; } public void setTDept(TDept TDept) {  this.TDept = TDept; } public String getEName() {  return this.EName; } public void setEName(String EName) {  this.EName = EName; }}


 

 

 

 

配置的TDept.hbm.xml如下:

 

<?xml version="1.0" encoding="utf-8"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><!--     Mapping file autogenerated by MyEclipse Persistence Tools--><hibernate-mapping>    <class name="com.svse.entity.TDept" table="T_DEPT" schema="SCOTT">        <id name="DId" type="java.lang.Long">            <column name="D_ID" precision="22" scale="0" />            <generator class="sequence" >             <param name="sequence">dept_seq</param>            </generator>        </id>        <property name="DName" type="java.lang.String">            <column name="D_NAME" length="20" not-null="true" />        </property>        <property name="DRemark" type="java.lang.String">            <column name="D_REMARK" length="100" not-null="true" />        </property>        <!-- 如果在删除一方的时候把多方也删掉,则在一方的set上配置cascade="delete" ,否则在删除一方的时候,如果找到子记录,则报错,违反约束条件 -->        <set name="TEmps" inverse="true" cascade="delete">            <key>                <column name="D_ID" precision="22" scale="0" not-null="true" />            </key>            <one-to-many class="com.svse.entity.TEmp" />        </set>    </class></hibernate-mapping>


TEmp.hbm.xml如下:

 

<?xml version="1.0" encoding="utf-8"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><!--     Mapping file autogenerated by MyEclipse Persistence Tools--><hibernate-mapping>    <class name="com.svse.entity.TEmp" table="T_EMP" schema="SCOTT">        <id name="EId" type="java.lang.Long">            <column name="E_ID" precision="22" scale="0" />            <generator class="sequence" >             <param name="sequence">emp_seq</param>            </generator>        </id>                <!-- 在批量添加多方的时候级联添加一方,配置cascade="save-update" -->        <many-to-one name="TDept" class="com.svse.entity.TDept" fetch="select" cascade="save-update">             <column name="D_ID" precision="22" scale="0" not-null="true" />        </many-to-one>                        <property name="EName" type="java.lang.String">            <column name="E_NAME" length="20" not-null="true" />        </property>    </class></hibernate-mapping>


 

 

 

用Junit测试添加多方,同时自动添加一方:

////测试:添加多方时级联添加一方 @Test public void test1(){  TDept dept=new TDept();  dept.setDName("开发3部");  dept.setDRemark("it is good....");    //第一个员工对象  TEmp emp1=new TEmp();  emp1.setEName("aaa");  emp1.setTDept(dept);    //第二个员工对象  TEmp emp2=new TEmp();  emp2.setEName("bbb");  emp2.setTDept(dept);   //第二个员工对象  TEmp emp3=new TEmp();  emp3.setEName("ccc");  emp3.setTDept(dept);    List<TEmp> empList=new ArrayList<TEmp>();  empList.add(emp1);  empList.add(emp2);  empList.add(emp3);  empService.addManyToOne(empList);//添加员工,在这里传一个list      System.out.println("dept & emps have been saved..."); }


 

 

addManyToOne(empList)这个添加员工方法的代码如下,因为一次要添加多个员工,所以传进去的是一个Lis集合,批量添加


 

/****** * 批量添加员工 * @param li */public void addManyToOne(List<TEmp> li) {System.out.println("传进来几个emp:  "+li.size());Session session=null;try {session=getHibernateTemplate().getSessionFactory().openSession();//获取sessionsession.beginTransaction();//开启事务//创建员工对象TEmp emp=null;//循环获取员工对象for(int i=0;i<li.size();i++){emp=(TEmp)li.get(i);System.out.println("第"+(i+1)+"个name是:"+emp.getEName());getHibernateTemplate().save(emp);//保存}session.getTransaction().commit();//提交事务} catch (RuntimeException re) {session.beginTransaction().rollback();throw re;} finally{session.close();}}


 

注意在多方配置casacde="save-update",在保存多方的时候,会自动保存一方

 

 

还有一种情况就是在添加一方的同时添加多方,配置差不多,就是在一方的set上配置cascade="save-update"

 

Junit测试代码如下:

 

////测试:添加一方的时候添加很多个多方@Testpublic void test1(){TDept dept=new TDept();dept.setDName("开发3部");dept.setDRemark("it is good....");//第一个员工对象TEmp emp1=new TEmp();emp1.setEName("aaa");emp1.setTDept(dept);//第二个员工对象TEmp emp2=new TEmp();emp2.setEName("bbb");emp2.setTDept(dept);//第三个员工对象TEmp emp3=new TEmp();emp3.setEName("ccc");emp3.setTDept(dept); Set emps = new HashSet(0); emps.add(emp1); emps.add(emp2); emps.add(emp3); dept.setTEmps(emps);  //添加部门 deptService.add(dept);  System.out.println("dept & emps have been saved...");}


 

TDept.hbm.xml配置如下

 

<?xml version="1.0" encoding="utf-8"?><!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN""http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><!--     Mapping file autogenerated by MyEclipse Persistence Tools--><hibernate-mapping>    <class name="com.svse.entity.TDept" table="T_DEPT" schema="SCOTT">        <id name="DId" type="java.lang.Long">            <column name="D_ID" precision="22" scale="0" />            <generator class="sequence" >            <param name="sequence">dept_seq</param>            </generator>        </id>        <property name="DName" type="java.lang.String">            <column name="D_NAME" length="20" not-null="true" />        </property>        <property name="DRemark" type="java.lang.String">            <column name="D_REMARK" length="100" not-null="true" />        </property>        <!-- 如果想在添加一方的时候添加多方,则在一方配置cascade="save-update",在多方不需要添加其它配置 -->        <set name="TEmps" inverse="true" cascade="save-update">            <key>                <column name="D_ID" precision="22" scale="0" not-null="true" />            </key>            <one-to-many class="com.svse.entity.TEmp" />        </set>    </class></hibernate-mapping>

 

 

其它:

      如果在一方设置casacde="remove",则表示在删除一方的时候,会删除与它关联的实体对象,如果没有设置这个属性,那么当删除一方的时候,如果找到对应的子记录,则删除报错,违反约束。


最后,欢迎访问风格清新简洁的轻博客网站[指尖一刻]