3、Hibernate一对多及多对多操作


一.表与表之间的关系

1.一对多 (老板与雇员)

  • 一对多通过外键建立关系

2.多对多 (老师和学生)

  • 一个用户里面可以有多个角色,一个角色里面可以有多个用户
  • 多对多需要创建第三张表维护关系

二.hibernate 一对多操作

1.一对多映射配置

举例:

  • 老板和 雇员 是一对多的关系

(1)创建两个基本的实体类

老板和雇员

//老板
public class Boss {
    private int bid;
    private String bName;
	......
    }
//雇员
public class Employee {
    private int eid;
    private String eName;
    ......
    }

(2)让两个实体之间有相互表示的属性

  • 在“多” 的一方 (“雇员类” 中 表示 “老板”)
private Set<Employee> employees = new HashSet<> () ;
//set  get
public Set<Employee> getEmployees() {return employees;    }
public void setEmployees(Set<Employee> employees) {this.employees = employees; }

  • 在“一” 的一方 (“老板类” 中 表示 “雇员”集合)
private Boss boss;
//set  get
 public Boss getBoss() {return boss;    }
 public void setBoss(Boss boss) {this.boss = boss;  }

(3)配置映射关系

  • 一般一个实体类对应一个映射文件
  • 在“一” 的一方 老板的配置文件中
<?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 name="ph.com.ManyToOne.Boss" table="t_boss">

        <id name="bid">
            <generator class="native"/>
        </id>
        <property name="bName"/>
        
<!-- 在老板映射文件中 表示所有雇员
		使用set标签表示所有雇员,set标签里面有name属性
		属性值写在老板实体类里面表示雇员的set集合名称
-->
        <set name="employees">
        <!-- 一对多建表,有外键
		hibernate机制,双向维护外键,在一和多的地方都配置外键
		column属性值,外键名称                        
		(名称可以随便起,就是  雇员  表中的外键名称,不过要注意和雇员中外键名称保持一致)               
	-->
        <key column="bossid"></key>
       <!-- 老板所有的雇员,class里面写雇员实体类全路径	(注意标签顺序)		--> 
        <one-to-many class="ph.com.ManyToOne.Employee"></one-to-many>
        
        </set>
    </class>
</hibernate-mapping>


  • 在“多” 的一方 雇员的配置文件中
 <?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 name="ph.com.ManyToOne.Employee" table="t_employee">
         <id name="eid">
            <generator class="native"/>
        </id>
        <property name="eName"/>

<!-- 表示雇员所属老板
		name属性:因为在雇员实体使用Boss对象表示老板。     (写老板对象名称)
		class属性:Boss类全路径     
		column属性:外键名称                             
		 (名称可以随便起,就是  雇员  表中的外键名称,不过要注意和老板中外键名称保持一致)       
		(注意标签顺序)    
 -->
<many-to-one name="boss" class="ph.com.ManyToOne.Boss" column="bossid"/>
               
    </class>
</hibernate-mapping>

2.一对多联级保存

(1) 完整写法

		Boss boss = new Boss();
        Employee employee = new Employee();
        boss.setbName("我是boss1");
        employee.seteName("我是employee1");
//建立关系
//把雇员对象,放到老板对象的set集合里面
        boss.getEmployees().add(employee);
        employee.setBoss(boss);

        session.saveOrUpdate(boss);
        session.saveOrUpdate(employee);

???如果创建好雇员对象,直接添加外键值,何必再动用老板类,为什么这样不行
答:一试便知,因为hibernate中通过对象操作,而对象中没有外键这个属性字段

(2) 简化写法

  • 一般根据客户添加联系人
  • 第一步 在老板映射文件中进行配置 在set标签中加入 cascade=“save-update”
<set name="employees" cascade="save-update">
  • 第二步 创建雇员和老板对象,只需要把雇员放到老板里面就可以了,最终只需要操作添加老板那一步就可以
Employee employee = new Employee();
boss.setbName("我是boss2");
employee.seteName("我是employee2");
      
//建立关系
//把雇员(employee)对象,放到老板(boss)对象的set集合里面
boss.getEmployees().add(employee);
session.saveOrUpdate(boss);

3.一对多联级删除

(1) 删除某个老板,把客户里面所有的雇员删除

(2)具体实现

  • 第一步 在客户映射文件set标签,进行配置
<set name="employees" cascade="save-update,delete">
  • 第二步 在代码中直接删除老板(boss)
  • 其一  根据id查询对象,调用session里面delete方法删除
    
Boss boss = session.get(Boss.class,2);
        session.delete(boss);

5. 更改主键 (更改雇员的老板)

1.查询新的老板对象
2.查询想要修改的雇员
3.将雇员添加进新的老板对象中
4.将新老板添加进雇员对象中
(和原来的老板没有关系)

  		Boss boss = session.get(Boss.class,2);
        Employee employee = session.get(Employee.class, 1);
        boss.getEmployees().add(employee);
        employee.setBoss(boss);

        //持久态自动提交

5.inverse属性

上述有一些问题,会更新两次主键(因为hibernate双向维护主键的机制)

Hibernate: 
    update
        t_employee 
    set
        eName=?,
        bossid=? 
    where
        eid=?
Hibernate: 
    update
        t_employee 
    set
        bossid=? 
    where
        eid=?

在老板(Boss)的一方:(在set标签中,加入inverse属性)
inverse:
true:放弃维护外键
false:维护外键(默认值)

<set name="employees" cascade="save-update,delete"   inverse="true">
......

三.hibernate 多对多操作

1.多对多映射配置

(1).第一步 创建实体类 -----老师和学生

(2).第二步 创建映射配置文件

  • 老师
<hibernate-mapping>
    <class name="ph.com.ManyToMany.Teacher" table="t_teacher">
        <id name="tid">
            <generator class="native"/>
        </id>
        <property name="tName"/>


        <!--
         1. name:老师中学生的set集合
         2.第三张关系表的名称
         -->
        <set name="studentSet" table="t_st">
            <!--key标签:
            配置当前映射文件在第三张表的外键名称
            -->
           <key column="t3id"></key>
            <!--colum:学生在第三张表中的外键名称
                class: 学生的实体类路径
           -->
           <many-to-many column="s3id" class="ph.com.ManyToMany.Student"></many-to-many>
       </set>
   </class>
</hibernate-mapping>
  • 学生
<hibernate-mapping>
    <class name="ph.com.ManyToMany.Student" table="t_student">
        <id name="sid">
            <generator class="native"/>
        </id>
        <property name="sName"/>

        <set name="teacherSet" table="t_st" >
            <key column="s3id"></key>
            <many-to-many column="t3id" class="ph.com.ManyToMany.Teacher"></many-to-many>
        </set>
    </class>
</hibernate-mapping>

2.多对多联级保存(重点)

例如:根据老师保存学生

(1)第一步 在老师映射文件中set标签中添加 cascade值 save-update 进行配置

 <set name="studentSet" table="t_st" cascade="save-update">
 ......

(2)第二步

 //建立关系
        //将学生放入老师里面

        //teacher1----student1/student2
        teacher1.getStudentSet().add(student1);
        teacher1.getStudentSet().add(student2);

        //teacher2----student2/student3
        teacher2.getStudentSet().add(student2);
        teacher2.getStudentSet().add(student3);


        session.save(teacher1);
        session.save(teacher2);

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值