内容简介:hibernate教程--关联关系的映射详解
1.1 Hibernate关联关系的映射
1.1.1 实体之间的关系:
实体之间有三种关系:
* 一对多:
* 一个用户,生成多个订单,每一个订单只能属于一个用户.
* 建表原则:
* 在多的一方创建一个字段,作为外键,指向一的一方的主键.
* 多对多:
* 一个学生可以选择多门课程,一个课程可以被多个学生选择.
* 建表原则:
* 创建第三张表,中间表至少有两个字段,分别作为外键指向多对多双方主键.
* 一对一:(特殊.最少.)
* 一个公司只能有一个注册地址,一个注册地址,只能被一个公司使用.(否则将两个表建到一个表.)
* 建表原则:
* 唯一外键:
* 一对一的双方,假设一方是多的关系.需要在多的一方创建一个字段,作为外键.指向一的一方的主键.但是在外键添加一个unique.
* 主键对应:
* 一对一的双方,通过主键进行关联.
1.1.2 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="com.sihai.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="com.sihai.hibernate3.demo2.Order"/> </set> </class> </hibernate-mapping>
Order.hbm.xml
<hibernate-mapping> <class name="com.sihai.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="com.sihai.hibernate3.demo2.Customer"/> </class> </hibernate-mapping>
第三步:将映射放到核心配置文件中.
1.1.3 Hibernate中级联保存的效果:
级联:操作当前对象的时候,关联的对象如何处理.
cascade=”save-update”
级联方向性:
* 保存客户的时候,选择级联订单.
* 保存订单的时候,选择级联客户.
1.1.4 Hibernate中级联删除的效果:
cascade=”delete”
1.1.5 Hibernate中的级联取值:
none:不使用级联
save-update:保存或更新的时候级联
delete:删除的时候级联
all:除了孤儿删除以外的所有级联.
delete-orphan:孤儿删除(孤子删除).
* 仅限于一对多.只有一对多时候,才有父子存在.认为一的一方是父亲,多的一方是子方.
* 当一个客户与某个订单解除了关系.将外键置为null.订单没有了所属客户,相当于一个孩子没有了父亲.将这种记录就删除了.
all-delete-orphan:包含了孤儿删除的所有的级联.
1.1.6 双向维护产生多余的SQL:
配置inverse=”true”:在那一端配置.那么那一端放弃了外键的维护权.
* 一般情况下,一的一方去放弃.
cascade:操作关联对象.
inverse:控制外键的维护.
package com.sihai.hibernate3.demo2; import org.hibernate.Session; import org.hibernate.Transaction; import org.junit.Test; import com.sihai.utils.HibernateUtils; /** * 一对多的测试 * @author sihai * */ public class HibernateTest2 { @Test // 区分cascade和inverse // 在Customer.hbm.xml中的<set>上配置 cascade="save-update" inverse="true" public void demo11(){ Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); Customer customer = new Customer(); customer.setCname("张三"); Order order = new Order(); order.setAddr("西三旗"); customer.getOrders().add(order); // 客户是否存到数据库:存 // 订单是否存到数据库:存 cascade="save-update".外键是null. session.save(customer); tx.commit(); session.close(); } @Test // 双向维护:自动更新数据库,产生多余的SQL. // 双方都有外键的维护能力.必须让其中一方放弃外键的维护权.(一般情况下都是一的放弃.) public void demo10(){ Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); Customer customer = (Customer) session.get(Customer.class, 1); Order order = (Order) session.get(Order.class, 2); customer.getOrders().add(order); order.setCustomer(customer); tx.commit(); session.close(); } @Test // 孤儿删除: // 在Customer.hbm.xml中<set>上配置cascade="delete-orhpan" public void demo9(){ Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); // 让1号客户与1号订单解除关系: Customer customer = (Customer) session.get(Customer.class, 1); Order order = (Order) session.get(Order.class, 1); customer.getOrders().remove(order); tx.commit(); session.close(); } @Test // 级联删除:删除订单的时候,级联删除客户. public void demo8(){ Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); Order order = (Order) session.get(Order.class, 1); session.delete(order); tx.commit(); session.close(); } @Test // 级联删除:删除客户的时候级联删除订单. // 在Customer.hbm.xml的<set>标签上配置cascade="delete" public void demo7(){ Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); // 级联删除:先查询,在删除的方式. Customer custoemr = (Customer) session.get(Customer.class, 1); session.delete(custoemr); tx.commit(); session.close(); } @Test // 删除一个客户: // 默认的情况下,将外键置为null,删除数据记录. public void demo6(){ Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); // 删除的时候有两种: // 先查询在删除的情况: Customer customer = (Customer) session.get(Customer.class, 1); session.delete(customer); tx.commit(); session.close(); } @Test // 测试对象的导航关系: public void demo5(){ 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("上地"); 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); tx.commit(); session.close(); } @Test // 保存订单级联客户. // 在Order.hbm.xml中<many-to-one>配置cascade属性:级联保存 public void demo4(){ Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); // 定义客户: Customer customer = new Customer(); customer.setCname("郭浩"); // 定义订单: Order order = new Order(); order.setAddr("西三旗中腾建华"); order.setCustomer(customer); customer.getOrders().add(order); // 保存的时候只保存一方: session.save(order); tx.commit(); session.close(); } @Test // 保存客户级联订单. // <set>集合是客户的关联订单对象的集合.所以在<set>上配置一个属性:cascade="save-update" public void demo3(){ Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); // 定义客户: Customer customer = new Customer(); customer.setCname("郭浩"); // 定义订单: Order order = new Order(); order.setAddr("西三旗中腾建华"); order.setCustomer(customer); customer.getOrders().add(order); // 保存的时候只保存一方: session.save(customer); tx.commit(); session.close(); } @Test // 保存客户和订单的时候,是否可以只保存其中的一方?不行的报一个异常:一个持久态对象关联一个瞬时的对象. public void demo2(){ Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); // 定义客户: Customer customer = new Customer(); customer.setCname("金刚"); // 定义订单: Order order = new Order(); order.setAddr("五道口"); order.setCustomer(customer); customer.getOrders().add(order); // 保存的时候只保存一方: session.save(customer); tx.commit(); session.close(); } @Test // 向客户表插入一个客户,在订单表中插入两个订单. 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(); } }
1.1.7 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
<hibernate-mapping> <class name="com.sihai.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"> <!-- <key>中column写 当前类在中间表的外键.--> <key column="sno"></key> <!-- <many-to-many>中class:另一方类的全路径. column:另一方在中间表中外键名称--> <many-to-many class="com.sihai.hibernate3.demo3.Course" column="cno"/> </set> </class> </hibernate-mapping>
Course.hbm.xml
<hibernate-mapping> <class name="com.sihai.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"> <!-- <key>中column:当前类在中间表中外键 --> <key column="cno"></key> <!-- <many-to-many>中class:另一方的类全路径. column:另一方在中间表中外键名称 --> <many-to-many class="com.sihai.hibernate3.demo3.Student" column="sno"/> </set> </class> </hibernate-mapping>
第三步:将映射文件加入到核心配置文件中:
测试:
package com.sihai.hibernate3.demo3; import org.hibernate.Session; import org.hibernate.Transaction; import org.junit.Test; import com.sihai.utils.HibernateUtils; /** * 多对多的测试类: * * @author sihai * */ public class HibernateTest3 { @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(); } @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 // 级联操作:级联保存:保存学生关联课程 // 在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 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(); } }
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- MFC 消息映射机制详解
- hibernate教程--关联关系的映射详解
- MyBatis之Mapper XML 文件详解(五)-自动映射查询结果
- Android 进程通讯机制之 Binder(信使)架构以及内存映射详解
- MyBatis从入门到精通(十一):MyBatis高级结果映射之一对多映射
- MyBatis从入门到精通(九):MyBatis高级结果映射之一对一映射
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
计算机科学概论(第11版)
J. Glenn Brookshear / 刘艺、肖成海、马小会、毛倩倩 / 人民邮电出版社 / 2011-10-1 / 69.00元
本书多年来一直深受世界各国高校师生的欢迎,是美国哈佛大学、麻省理工学院、普林斯顿大学、加州大学伯克利分校等许多著名大学的首选教材,对我国的高校教学也产生了广泛影响。 本 书以历史眼光,从发展的角度、当前的水平以及现阶段的研究方向等几个方面,全景式描绘了计算机科学各个子学科的主要领域。在内容编排上,本书很好地兼顾了 学科广度和主题深度,把握了最新的技术趋势。本书用算法、数据抽象等核心思想贯穿各......一起来看看 《计算机科学概论(第11版)》 这本书的介绍吧!