hibernate教程--关联关系的映射详解

栏目: Hibernate · 发布时间: 8年前

内容简介: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();
	}
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Ruby on Rails社区网站开发

Ruby on Rails社区网站开发

布拉德伯纳 / 柳靖 / 2008-10 / 55.00元

《Ruby on Rails社区网站开发》全面探讨创建完整社区网站的开发过程。首先介绍开发一个内容简单的管理系统,之后逐渐添加新特性,以创建更完整的、使用Ruby on Rails 的Web 2.0 社区网站。还给出了开发和测试中的一些建议和提示,同时指导如何使网站更生动以及维护得更好。《Ruby on Rails社区网站开发》也探讨了如何与Flickr 、Google Maps 等其他平台集成,......一起来看看 《Ruby on Rails社区网站开发》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具