实体之间的关系
  实体之间有三种关系
    一对多:一个用户,生成多个订单,每一个订单只能属于一个用户
      建表原则:在多的一方创建一个字段,作为外键,指向一的一方的主键
    多对多:一个学生可以选择多门课程,一个课程可以被多个学生选择
      建表原则:创建第三张表,中间表至少有两个字段,分别作为外键指向多对多双方主键
    一对一(很少用,因为其实可以将两张表建成一张表):一个公司只能有一个注册地址,一个注册地址,只能被一个公司使用
      建表原则
        唯一外键:一对一的双方,假设一方是多的关系.需要在多的一方创建一个字段,作为外键.指向一的一方的主键.但是在外键添加一个unique
        主键对应:一对一的双方,通过主键进行关联
  

Hibernate中一对多的配置:(*****最重要)
  第一步:创建两个实体
    客户实体:

public class Customer {
  private Integer cid;
  private String cname;
  // 一个客户有多个订单.
  private Set<Order> orders = new HashSet<Order>();
  public Integer getCid() {
    return cid;
  }
  public void setCid(Integer cid) {
    this.cid = cid;
  }
  public String getCname() {
    return cname;
  }
  public void setCname(String cname) {
    this.cname = cname;
  }
  public Set<Order> getOrders() {
    return orders;
  }
  public void setOrders(Set<Order> orders) {
    this.orders = orders;
  }
}

    订单实体:

public class Order {
  private Integer oid;
  private String addr;
  // 订单属于某一个客户.放置一个客户的对象.
  private Customer customer;
  public Integer getOid() {
    return oid;
  }
  public void setOid(Integer oid) {
    this.oid = oid;
  }
  public String getAddr() {
    return addr;
  }
  public void setAddr(String addr) {
    this.addr = addr;
  }
  public Customer getCustomer() {
    return customer;
  }
  public void setCustomer(Customer customer) {
    this.customer = customer;
  }
}

  第二步:建立映射
    Customer.hbm.xml

<hibernate-mapping>
  <class name="cn.yzu.hibernate3.demo2.Customer" table="customer">
    <!-- 配置唯一标识 -->
    <id name="cid" column="cid">
      <generator class="native"/>
    </id>
    <!-- 配置普通属性 -->
    <property name="cname" column="cname" length="20"/>
    <!-- 建立映射 -->
    <!-- 配置一个集合 <set>的name:Customer对象中的关联对象的属性名称. -->
    <set name="orders">
      <!-- <key>标签中column:用来描述一对多多的一方的外键的名称. -->
      <key column="cno"></key>
      <!-- 配置一个<one-to-many>标签中class属性:订单的类的全路径 -->
      <one-to-many class="cn.yzu.hibernate3.demo2.Order"/>
    </set>
  </class>
</hibernate-mapping>

    Order.hbm.xml

<hibernate-mapping>
  <class name="cn.yzu.hibernate3.demo2.Order" table="orders">
    <!-- 配置唯一标识 -->
    <id name="oid" column="oid">
      <generator class="native"/>
    </id>
    <!-- 配置普通属性 -->
    <property name="addr" column="addr" length="50"/>
    <!-- 配置映射 -->
    <!-- <many-to-one>标签
      name :关联对象的属性的名称.
      column :表中的外键名称.
      class :关联对象类的全路径
    -->
    <many-to-one name="customer" column="cno" class="cn.yzu.hibernate3.demo2.Customer"/>
  </class>
</hibernate-mapping>

  第三步:测试

// 向客户表插入一个客户,在订单表中插入两个订单.
public void demo1(){
  Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
// 定义一个客户:
Customer customer = new Customer();
customer.setCname("郭浩");
// 定义两个订单:
Order order1 = new Order();
order1.setAddr("西三旗中腾");
Order order2 = new Order();
order2.setAddr("西三旗金燕龙");
// 建立关系:
order1.setCustomer(customer);
order2.setCustomer(customer);
customer.getOrders().add(order1);
customer.getOrders().add(order2);
session.save(customer);
session.save(order1);
session.save(order2);
tx.commit();
session.close();
}

Hibernate中级联保存(删除...)的效果
  级联:操作当前对象的时候,关联的对象如何处理

<set name="orders" cascade="save-update,delete">
<key column="cno"></key>
<one-to-many class="cn.yzu.hibernate3.demo2.Order"/>
</set>
// 定义客户:
Customer customer = new Customer();
customer.setCname("郭浩");
// 定义订单:
Order order = new Order();
order.setAddr("西三旗中腾建华");
order.setCustomer(customer);//如果不写这句,orders的cno为null
customer.getOrders().add(order);
// 保存的时候只需保存一方,级联保存订单
session.save(customer);  

  对象导航
    

    1、在配置文件中需要配置了2端cascade="save-update"
    2、order1关联到customer 而customer没有关联到order1
    3、customer关联到order2 order3 而order2 order3 没有关联到customer
    问题:
      session.save(order1) 插入几条记录----4
      session.save(customer) 插入几条记录----3
      session.save(order2) 插入几条记录-----1

// 定义一个客户:
Customer customer = new Customer();
customer.setCname("金刚");
// 定义三个订单
Order order1 = new Order();
order1.setAddr("西三旗");
Order order2 = new Order();
order2.setAddr("上地");
Order order3 = new Order();
order3.setAddr("五道口");
order1.setCustomer(customer);
customer.getOrders().add(order2);
customer.getOrders().add(order3);
// session.save(order1); // 共发送4条insert语句:
// session.save(customer);// 共发送3条insert语句:
session.save(order2);// 共发送1条insert语句:

Hibernate中的级联取值
  none :不使用级联
  dave-update :保存或更新的时候级联
  delete :删除的时候级联
  all :除了孤儿删除以外的所有级联.
  delete-orphan :孤儿删除(孤子删除).
    仅限于一对多.只有一对多时候,才有父子存在.认为一的一方是父亲,多的一方是子方.
    当一个客户与某个订单解除了关系.将外键置为null.订单没有了所属客户,相当于一个孩子没有了父亲.将这种记录就删除了.
  all-delete-orphan :包含了孤儿删除的所有的级联.
双向维护产生多余的SQL(多发送SQL语句)

  

  需求:将第二个订单的cno改为1

Customer customer = (Customer) session.get(Customer.class, 1);
Order order = (Order) session.get(Order.class, 2);
customer.getOrders().add(order);
order.setCustomer(customer);

  hibernate发送的部分SQL语句:

  

    发送了两次update语句!!

  原因

  解决办法:配置inverse=”true”:在那一端配置.那么那一端放弃了外键的维护权(一般情况下,一的一方去放弃)

<set name="orders" cascade="save-update" inverse="true">
<key column="cno"></key>
<one-to-many class="cn.yzu.hibernate3.demo2.Order"/>
</set>

   配置后执行原语句hibernate只发送一条更新语句!(cascade:操作关联对象,inverse:控制外键的维护)

Hibernate的多对多的配置
  第一步:创建实体类
    学生的实体:

public class Student {
  private Integer sid;
  private String sname;
  // 一个学生选择多门课程:
  private Set<Course> courses = new HashSet<Course>();
  public Integer getSid() {
    return sid;
  }
  public void setSid(Integer sid) {
    this.sid = sid;
  }
  public String getSname() {
    return sname;
  }
  public void setSname(String sname) {
    this.sname = sname;
  }
  public Set<Course> getCourses() {
    return courses;
  }
  public void setCourses(Set<Course> courses) {
    this.courses = courses;
  }
}

    课程的实体:

public class Course {
  private Integer cid;
  private String cname;
  // 一个课程被多个学生选择:
  private Set<Student> students = new HashSet<Student>();
  public Integer getCid() {
    return cid;
  }
  public void setCid(Integer cid) {
    this.cid = cid;
  }
  public String getCname() {
    return cname;
  }
  public void setCname(String cname) {
    this.cname = cname;
  }
  public Set<Student> getStudents() {
    return students;
  }
  public void setStudents(Set<Student> students) {
    this.students = students;
  }
}

  第二步:建立映射
    Student.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!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="cn.yzu.hibernate3.demo3.Student" table="student">
<!-- 配置唯一标识 -->
<id name="sid" column="sid">
<generator class="native"/>
</id>
<!-- 配置普通属性 -->
<property name="sname" column="sname" length="20"/>
<!-- 配置关联映射 -->
<!-- <set>标签 name:对应学生中的课程集合的名称 table:中间表名称. -->
<set name="courses" table="stu_cour" cascade="save-update,delete">
<!-- <key>中column写 当前类在中间表的外键.-->
<key column="sno"></key>
<!-- <many-to-many>中class:另一方类的全路径. column:另一方在中间表中外键名称-->
<many-to-many class="cn.yzu.hibernate3.demo3.Course" column="cno"/>
</set>
</class>
</hibernate-mapping>

    Course.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!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="cn.yzu.hibernate3.demo3.Course" table="course">
<!-- 配置唯一标识 -->
<id name="cid" column="cid">
<generator class="native"/>
</id>
<!-- 配置普通属性 -->
<property name="cname" column="cname" length="20"/>
<!-- 配置与学生关联映射 -->
<!-- <set>中name:对应当前类中的学生的集合的名称 table:中间表的名称-->
<set name="students" table="stu_cour" inverse="true">
<!-- <key>中column:当前类在中间表中外键 -->
<key column="cno"></key>
<!-- <many-to-many>中class:另一方的类全路径. column:另一方在中间表中外键名称 -->
<many-to-many class="cn.yzu.hibernate3.demo3.Student" column="sno"/>
</set>
</class>
</hibernate-mapping>

  第三步:测试

public class HibernateTest3 {
@Test
// 保存学生和课程.为学生选择一些课程:
public void demo1() {
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
// 创建学生:
Student student1 = new Student();
student1.setSname("张三");
Student student2 = new Student();
student2.setSname("李四");
// 创建课程:
Course course1 = new Course();
course1.setCname("Java语言");
Course course2 = new Course();
course2.setCname("Android语言");
// 张三选1号和2号课
student1.getCourses().add(course1);
student1.getCourses().add(course2);
course1.getStudents().add(student1);
course2.getStudents().add(student1);
student2.getCourses().add(course1);
course1.getStudents().add(student2);
// 执行保存:
session.save(student1);
session.save(student2);
session.save(course1);
session.save(course2);
tx.commit();
session.close();
}
@Test
// 级联操作:级联保存:保存学生关联课程
// 在Student.hbm.xml中配置<set>上 cascade="save-update"
public void demo2() {
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
// 创建学生:
Student student1 = new Student();
student1.setSname("王五");
// 创建课程:
Course course1 = new Course();
course1.setCname("PHP语言");
student1.getCourses().add(course1);
course1.getStudents().add(student1);
session.save(student1);
tx.commit();
session.close();
}
@Test
// 级联删除:在多对多中很少使用.
// 删除:删除学生同时删除学生关联选课
public void demo3(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
Student student = (Student) session.get(Student.class, 3);
session.delete(student);
tx.commit();
session.close();
}
@Test
// 多对多的学生退选.
public void demo4(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
// 查询一号学生
Student student = (Student) session.get(Student.class, 1);
Course course = (Course) session.get(Course.class, 2);
student.getCourses().remove(course);
tx.commit();
session.close();
}
}

Hibernate关联关系的映射的更多相关文章

  1. 【Hibernate】Hibernate关联关系的映射

    一.实体之间的关系 二.一对多的配置 2.1 第一步创建两个实体 2.2 第二步:配置映射文件 2.3 第三步:将映射放到核心配置文件中 三.级联 3.1 Hibernate中级联保存的效果 3.2 ...

  2. Hibernate关联关系映射

    1.  Hibernate关联关系映射 1.1.  one to one <class name="Person"> <id name="id" ...

  3. Hibernate的关联映射——双向1-N关联

    Hibernate的关联映射--双向1-N关联 对于1-N的关联,Hibernate推荐使用双向关联,而且不要让1的一端控制关联关系,而是用N的一端控制关联关系.双线的1-N关联和N-1关联是两种相同 ...

  4. Hibernate的关联映射——单向1-N关联

    Hibernate的关联映射--单向1-N关联 单向1-N关联的持久化类里需要使用集合属性.因为1的一端需要访问N的一端,而N的一端将以集合(Set)形式表现.从这个意义上来看,1-N(实际上还包括N ...

  5. Hibernate的关联映射——单向1-1关联

    Hibernate的关联映射--单向1-1关联 对于单向的1-1关联关系,需要在持久化类里增加代表关联实体的成员变量,并为该成员变量添加setter方法和getter方法.从持久化类的代码上看,单向1 ...

  6. Hibernate的关联映射——单向N-1关联

    Hibernate的关联映射--单向N-1关联 N-1是非常常见的关联关系,最常见的父子关系也是N-1关联,单向的N-1关联只需从N的一端可以访问1的一端. 为了让两个持久化类能够支持这种关联映射,程 ...

  7. Hibernate配置文件和映射元素解释

    象关系的映射是用一个XML文档来说明的.映射文档可以使用工具来生成,如XDoclet,Middlegen和AndroMDA等.下面从一个映射的例子开始讲解映射元素. AD:干货来了,不要等!WOT20 ...

  8. 【Hibernate步步为营】--映射合集汇总

    前几篇文章具体讨论了对象模型到关系模型的转化方法,对映射关系做了具体的了解,Hibernate将对象模型转化为对应的关系模型是通过使用对应的映射来完毕的(相同也能够使用注解),对于对象之间的关系的转化 ...

  9. Hibernate之关联映射(一对多和多对一映射,多对多映射)

    ~~~接着之前的Hibernate框架接着学习(上篇面试过后发现真的需要学习以下框架了,不然又被忽悠让去培训.)~~~ 1:Hibernate的关联映射,存在一对多和多对一映射,多对多映射: 1.1: ...

随机推荐

  1. unsigned无符号、有符号类型的符号拓展

    先看一段代码 #include <stdio.h> main(){ unsigned ; char b = a; printf("%d %d",a,b); ; } a输 ...

  2. 【Beta】第五次任务发布

    PM #100 日常管理&dev版宣传&设计报告管理后台. 后端 #101 完成收藏功能 完成管理员权限表的生成和接入(按位压缩权限表) 验收条件:收藏功能能够正常使用.能够区分常规用 ...

  3. mysql免安装使用(win7 64位系统)

    一.解压 二.以管理员身份运行cmd 三.cmd命令进入到解压后的mysql文件bin目录下 四.将mysql服务添加到windows服务中.cmd在bin目录下输入:mysqld -install  ...

  4. 线程间通信 GET POST

    线程间通信有三种方法:NSThread   GCD  NSOperation       进程:操作系统里面每一个app就是一个进程. 一个进程里面可以包含多个线程,并且我们每一个app里面有且仅有一 ...

  5. mysql索引失效

    在做项目的过程中,难免会遇到明明给mysql建立了索引,可是查询还是很缓慢的情况出现,下面我们来具体分析下这种情况出现的原因及解决方法   索引并不是时时都会生效的,比如以下几种情况,将导致索引失效: ...

  6. SDL 截图、录像、录像播放

    截图 使用sdl很简单,视频显示窗口大小,不是视频分辨率大小 int i = Sdl.SDL_SaveBMP(surfacePtr, path); if(i != 0) { MessageBox.Sh ...

  7. margin双边距的问题

    margin:20px;height:20px;float:left margin:20px;height:20px;float:left

  8. 深入理解javascript原型和闭包(13)-【作用域】和【上下文环境】

    上文简单介绍了作用域,本文把作用域和上下文环境结合起来说一下,会理解的更深一些. 如上图,我们在上文中已经介绍了,除了全局作用域之外,每个函数都会创建自己的作用域,作用域在函数定义时就已经确定了.而不 ...

  9. QQ空间HD(5)-添加左侧菜单栏内容

    DJIconView.m #import "DJIconView.h" @implementation DJIconView - (instancetype)initWithFra ...

  10. nyoj 448 寻找最大数(贪心专题)

    寻找最大数 时间限制:1000 ms  |  内存限制:65535 KB 难度:2   描述 请在整数 n 中删除m个数字, 使得余下的数字按原次序组成的新数最大, 比如当n=920813467185 ...