【SSH系列】Hibernate映射 -- 一对多关联映射

    映射原理
       一对多关联映射和多对一关联映射的映射原理是一样一样的,所以说嘛,知识都是相通的,一通百通,为什么说一对多关联映射和多对一关联映射是一样的呢?因为她们都是在多的一端加入一个外键,指向一的一段,关联关系都是在多的一端进行维护,只是我们在写映射的时候发生了变化。
       一对多和多对一的映射原理是一样的,但是她们之间也存在着小小的区别,毕竟世界上没有两片完全相同的叶子,她们之间的区别就是维护的关系不同,我们先来看多对一,多端维护一端的关系,在加载多端的时候,可以将一端加载上来;一对多,一端维护多端的关系,在加载一端的时候,可以将多端加载上来。一对多关联映射也存在两种策略,单向和双向,今天这篇博文,小编就来简单的介绍一下一对多关联映射,希望对有需要的小伙伴有帮助,不足之处,还请小伙伴们多多指教`(*∩_∩*)′。

   一对多单向关联映射

我们都知道,一个班级是由多个学生组成的,ok,今天的故事就从班级和学生开始拉开帷幕,我们依然从uml入手,首先我们来看对象模型,如下图所示:

从对象模型中,我们可以看出,Classes持有Student的一个引用,由于是单向关联,所以数据在加载Classes的时候,会把Student加载上来,但是Student并不知道Classes的存在。接着,我们开始来编写代码的部分。
第一步、编写实体Classes && Student,代码如下所示,首先我们来编写Classes,代码如下所示:

package com.bjpowernode.hibernate;
import java.util.Set;

public class Classes {

	private int id;
	private String name;
	private Set Students;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Set getStudents() {
		return Students;
	}
	public void setStudents(Set students) {
		Students = students;
	}

Student的代码如下所示:

	package com.bjpowernode.hibernate;

	public class Student {

		private int id;
		private String name;
		public int getId() {
			return id;
		}
		public void setId(int id) {
			this.id = id;
		}
		public String getName() {
			return name;
		}
		public void setName(String name) {
			this.name = name;
		}

	}

第二步、编写映射文件,首先编写Classes.hbm.xml代码如下所示:

	<?xml version="1.0"?>
	<!DOCTYPE hibernate-mapping PUBLIC
	    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
	<hibernate-mapping>
		<class name="com.bjpowernode.hibernate.Classes" table="t_classes">

			<id name="id">
				<generator class="native"/>
			</id>
			<property name="name"/>
			<set name = "students">

				<key column="classesid"/>
				<one-to-many class="com.bjpowernode.hibernate.Student"/>

			</set>
		</class>

	</hibernate-mapping>

接着编写Student.hbm.xml的代码,如下所示:

	<?xml version="1.0"?>
	<!DOCTYPE hibernate-mapping PUBLIC
	    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
	<hibernate-mapping>
	   <class name ="com.bjpowernode.hibernate.Student" table="t_student">
	   	<id name="id">
	   		<generator class="native"/>

	   	</id>
	   		<property name="name"/>

	   </class>

	</hibernate-mapping>

第三步、编写hibernate.cfg.xml的代码,建立数据库并且添加相应的映射,代码如下所示:

	<!DOCTYPE hibernate-configuration PUBLIC
		"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
		"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

	<hibernate-configuration>
		<session-factory >
			<!-- MySql数据库驱动 -->
			<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
			<!-- 数据库名称 -->
			<property name="hibernate.connection.url"> jdbc:mysql:///hibernate_one2many_1</property>
			<!-- 数据库的用户名 -->
			<property name="hibernate.connection.username">root</property>
			<!-- 数据库的密码 -->
			<property name="hibernate.connection.password">123456</property>
			<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
			<!-- 显示语句 -->
	        <property name="hibernate.show_sql">true</property>
	        <!-- 格式排版 -->
	        <!-- <property name="hibernate.format_sql">true</property> -->    

			<mapping resource="com/bjpowernode/hibernate/Student.hbm.xml"/>
			<mapping resource="com/bjpowernode/hibernate/Classes.hbm.xml"/>
		</session-factory>

</hibernate-configuration>

接着创建数据库,并且运行ExportDB,生成相应的表结构如下所示:


      接着,我们向表里面插入数据,代码如下所示:

	package com.bjpowernode.hibernate;

	import java.util.HashSet;
	import java.util.Set;
	import junit.framework.TestCase;
	import org.hibernate.Session;
	public void testSave2() {
		Session session = null;
		try {
			session = HibernateUtils.getSession();
			session.beginTransaction();
			Student student1 = new Student();
			student1.setName("张三");
			session.save(student1);

			Student student2 = new Student();
			student2.setName("李四");
			session.save(student2);

			Classes classes = new Classes();
			classes.setName("动力节点");

			Set students = new HashSet();
			students.add(student1);
			students.add(student2);
			classes.setStudents(students);

			//可以成功保存数据
			//但是会发出多余的update语句来维持关系
			session.save(classes);
			session.getTransaction().commit();
		}catch(Exception e) {
			e.printStackTrace();
			session.getTransaction().rollback();
		}finally {
			HibernateUtils.closeSession(session);
		}
	}

运行代码效果如下所示:

从上面的demo实例我们可以看出来,因为多端Student不知道Classes的存在,也就是Student不维护与Classes的关系,所以在保存Student的时候,字段classesid为空,如果该字段设置为非空,则将无法保存数据;因为Student不维护关系,而Classes维护关系,Classes将会发出多余的update语句。介绍完了一对多单向关联映射,接着我们来一起学习一下一对多双向关联映射,对象模型如下所示:

    双向关联映射

双向关联映射对比单向关联映射,对象的加载方向由单向变成了双向。我们依然以为Classes和Student为例进行讲解。
       第一步、编写实体Classes && Student,代码如下所示,首先我们来编写Classes,代码如下所示:

package com.bjpowernode.hibernate;

import java.util.Set;

public class Classes {

	private int id;
	private String name;
	private Set Students;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Set getStudents() {
		return Students;
	}
	public void setStudents(Set students) {
		Students = students;
	}

}

接着,编写Student的代码,如下所示:

package com.bjpowernode.hibernate;

public class Student {

	private int id;
	private String name;
	private Classes classes;

	public Classes getClasses() {
		return classes;
	}
	public void setClasses(Classes classes) {
		this.classes = classes;
	}
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}

}

第二步、编写映射文件,首先编写Classes.hbm.xml代码如下所示:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
	<class name="com.bjpowernode.hibernate.Classes" table="t_classes">

		<id name="id">
			<generator class="native"/>
		</id>
		<property name="name"/>
		<set name = "students">
			<key column="classesid"/>
			<one-to-many class="com.bjpowernode.hibernate.Student"/>

		</set>
	</class>

接着编写Student.hbm.xml的代码,如下所示:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
   <class name ="com.bjpowernode.hibernate.Student" table="t_student">
   	<id name="id">
   		<generator class="native"/>

   	</id>
   		<property name="name"/>
   		<many-to-one name="classes" column="classesid"/>

   </class>

</hibernate-mapping>

第三步、编写hibernate.cfg.xml的代码,建立数据库并且添加相应的映射,代码如下所示:

<!DOCTYPE hibernate-configuration PUBLIC
	"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
	<session-factory >
		<!-- MySql数据库驱动 -->
		<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
		<!-- 数据库名称 -->
		<property name="hibernate.connection.url"> jdbc:mysql:///hibernate_one2many_2</property>
		<!-- 数据库的用户名 -->
		<property name="hibernate.connection.username">root</property>
		<!-- 数据库的密码 -->
		<property name="hibernate.connection.password">123456</property>
		<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
		<!-- 显示语句 -->
        <property name="hibernate.show_sql">true</property>
        <!-- 格式排版 -->
        <!-- <property name="hibernate.format_sql">true</property> -->    

		<mapping resource="com/bjpowernode/hibernate/Student.hbm.xml"/>
		<mapping resource="com/bjpowernode/hibernate/Classes.hbm.xml"/>
	</session-factory>
</hibernate-configuration>

接着创建数据库,并且运行ExportDB,生成相应的表结构如下所示:

接着,我们向表里面插入数据,代码如下所示:

package com.bjpowernode.hibernate;
import java.util.HashSet;
import java.util.Set;
import junit.framework.TestCase;
import org.hibernate.Session;
public void testSave2() {
		Session session = null;
		try {
			session = HibernateUtils.getSession();
			session.beginTransaction();
			Student student1 = new Student();
			student1.setName("张三");
			session.save(student1);

			Student student2 = new Student();
			student2.setName("李四");
			session.save(student2);

			Classes classes = new Classes();
			classes.setName("动力节点");

			Set students = new HashSet();
			students.add(student1);
			students.add(student2);
			classes.setStudents(students);

			//可以成功保存数据
			//但是会发出多余的update语句来维持关系
			session.save(classes);
			session.getTransaction().commit();
		}catch(Exception e) {
			e.printStackTrace();
			session.getTransaction().rollback();
		}finally {
			HibernateUtils.closeSession(session);
		}

}

运行代码,效果如下所示:


       小编寄语:为什么多对一关联映射不存在单向一对多中的问题呢?在多对一关联映射里面,由于关系是在多的一端进行维护的,加载的时候从多的一端进行加载,当然没有问题。总结一下:在多对一关联映射中,如果用到,经常采用双向的方式来完成映射,弥补单向加载时的问题。ok,今天的hibernate一对多映射就介绍到这里,还请小伙伴们多多指教,在下一篇博文中,小编将继续介绍hibernate映射的相关知识,敬请期待……

时间: 2024-08-05 02:21:28

【SSH系列】Hibernate映射 -- 一对多关联映射的相关文章

【SSH进阶之路】Hibernate映射——一对多关联映射(七)

上上篇博文[SSH进阶之路]Hibernate映射--一对一单向关联映射(五),我们介绍了一对一的单向关联映射,单向是指只能从人(Person)这端加载身份证端(IdCard),但是反过来,不能从身份证端加载人得信息. 上篇博文[SSH进阶之路]Hibernate映射--一对一双向关联映射(六),双向关联映射解决了单向关联映射只能从一端加载信息的缺陷,当然,双向关联映射并不影响存储,只影响加载.下面我们开始今天的内容: 一对多关联映射 映射原理 一对多关联映射和多对一关联映射的映射原理是一致的,

【SSH进阶之路】Hibernate映射——多对多关联映射(八)

上篇博文[SSH进阶之路]Hibernate映射--一对多关联映射(七),我们介绍了一对多关联映射,它是多对多关联映射的基础. 多对多映射是现实生活中最常见的映射,也是最容易理解的映射.废话少说,直接开始. 映射原理 不论是单向关联还是双向关联都是通过第三张表,将两个表中的主键放到第三张做一个关联.用第三张表来解决可能会造成数据冗余的问题. 举例 一个用户(User)对多个角色(Role),一个角色对多个用户. 分类 单向的多对多关联映射(单向User--->Role) 对象模型 关系模型 实例

【SSH系列】Hibernate映射 -- 多对多关联映射

     映射原理 在数据库学习阶段,我们知道,如果实体和实体之间的关系是多对多,那么我们就抽出来第三张表,第一张表和第二张表的主键作为第三表的联合主键,结合我们的hibernate,多对多关联,无论是单向关联还是双向关联都是通过第三张表,将两个表中的主键放到第三张表中做一个关联,用第三张表来解决可能造成的数据冗余问题.今天这篇博文小编来简单的介绍一下hibernate中的多对多关联映射. 在某些系统中,一个用户可以有多个角色,一个角色也可以有多个用户,so,她们之间的关系就是多对多,多对多关联

【SSH进阶之路】Hibernate映射——一对一双向关联映射(六)

上篇博文[SSH进阶之路]Hibernate映射--一对一单向关联映射(五),我们介绍了一对一的单向关联映射,单向是指只能从人(Person)这端加载身份证端(IdCard),但是反过来,不能从身份证端加载人得信息.如图所示: 关键原因在于对象模型具有方向性: 单向:一端只能加载另一端,不能反过来. 双向:两端都可以加载另一端. 问题来了:如何我们想从身份证端(IdCard)加载人(Person),怎么办呢? 下面我们开始介绍一对一的双向关联映射. 映射原理 双向关联映射与单向关联映射的原理是一

【SSH进阶之路】Hibernate映射——一对一单向关联映射(五)

[SSH进阶之路]Hibernate基本原理(一) ,小编介绍了Hibernate的基本原理以及它的核心,采用对象化的思维操作关系型数据库. [SSH进阶之路]Hibernate搭建开发环境+简单实例(二),小编搭建了基本Hibernate的开发环境,并做了一个简单实例,对它的基本原理有了一个理性的认识. [SSH进阶之路]Hibernate基本映射(三),我们介绍了Hibernate的基本映射(即对一个实体进行映射)的相关概念,并给大家实现相关实例,比较简单. [SSH进阶之路]Hiberna

hibernate之关于使用连接表实现一对多关联映射

[Hibernate]之关于使用连接表实现一对多关联映射 基于中间表实现的一对多的关联映射,还是比较常见的. Person(人)和Group(组) Annotations配置 @Entity @Table(name="t_group") publicclass Group {     private Integer id;     private String name;     private Set<Person> persons=newHashSet<Perso

一步步学习Hibernate框架(四):采用jpa实现一对多关联映射(二)

上篇博客已经采用jpa注解来实现了一对多关联映射,将这种关联映射以外键的形式处理,现在来看看怎么以第三张表的形式处理.采用jpa注解来映射数据库要使用的jar包见上篇博客: 一步步学习Hibernate框架(三):采用jpa实现一对多关联映射(一) 现在看第二种方式:以第三张表的关系来体现 Group.java package com.tgb.zhudan; import java.util.List; import javax.persistence.CascadeType; import j

千山万水之Hibernate(六)——关联映射(一对多)

学习Hibernate的过程中,映射是比较重要的一部分,再说其中哪一种映射比较重要(或可以说是比较常用)呢?那一定很多人会想到一对多关联映射.之所以这样说,是因为在生活中很多这样的实例:班级-学生.企业-员工.文件夹-文件.试卷-题目等.至于生活中为什么会遇到这样大量一对多的情况,似乎是哲学方面的事情了,当然大家可以继续思考,而我们今天主要讨论Hibernate中的一对多. 原理分析 我们仍然拿班级.学生之间的关系做例子:一个班级包含多个学生.相应的实体关系图为: 单向关联 由图可知,由于单向的

Hibernate一对多关联映射的配置及其级联删除问题

首先举一个简单的一对多双向关联的配置: 一的一端:QuestionType类 package com.exam.entity; import java.util.Set; public class QuestionType { private String typeName; private char typeUniqueness; private Set quesion; public String getTypeName() { return typeName; } public void