一口一口吃掉Hibernate(五)——一对多单向关联映射

简介:       在上一篇博客《一口一口吃掉Hibernate(四)——多对一单向关联映射》中,介绍了多对一的关联映射,今天就反过来说一下一对多的单向关联映射。       可能有人会对这2篇博客的题目有点混淆不清,跟日常说的关系有点不同。

      在上一篇博客《一口一口吃掉Hibernate(四)——多对一单向关联映射中,介绍了多对一的关联映射,今天就反过来说一下一对多的单向关联映射。


      可能有人会对这2篇博客的题目有点混淆不清,跟日常说的关系有点不同。我们日常说的比如父子关系,夫妻关系都是说的双向关系,而现在讨论的则是单向关系,所以也就有了多对一和一对多的说法。


      二者的关系其实很简单,只是角度不同而已。比如说学生和班级的关系。如果从学生角度来看,是多对一的关系。而从班级角度来看,则是一对多的关系。说法很简单,但是在对象和关系的建立却是不一样的。


      先看一下一对多的类图(貌似好多人的聚合关系都画错了):


     Hibernate对于一对多的关系的处理,是通过操作Class端,间接操作或者自动操作Student端。比如添加,我直接添加Class端的数据,多个Student就会被添加自动添加进去。也可以通过这个Class获取到所有对应的学生信息。跟着我来配置一下吧:


      首先定义实体类【Class】【Student】

package com.bjpowernode.hibernate;

import java.util.Set;

/**
 * 班级类
 * @author Longxuan
 *
 */
public class Class {

	private int id;
	
	private String name;
	
	private Set<Student> students;

	public Set<Student> getStudents() {
		return students;
	}

	public void setStudents(Set<Student> students) {
		this.students = 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;
	}
}


package com.bjpowernode.hibernate;

/**
 * 学生类
 * @author Longxuan
 *
 */
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;
	}

	
}

       hibernate.cfg.xml配置文件和hibernate.properties配置文件跟上篇博文中的一致,只是数据库名不同而已。自行修改或者不修改都可。


      Hibernate提供了one-to-many来简化一对多的映射关系。不用我们自己再去实现,只需要在映射文件中进行配置即可:

<?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 package="com.bjpowernode.hibernate">
	<class name="Student" table="t_student">
		<id name="id">
			<generator class="native"/>
		</id>
		<property name="name"/>
	</class>
	
	<class name="Class" table="t_class">
		<id name="id">
			<generator class="native"/>
		</id>
		<property name="name"/>
		<!-- 设置Set,用于关联多个学生 -->
		<set name="students">
			<!-- 在t_student表中创建外键classid,与本表的id对应 -->
			<key column="classid"></key>
			<one-to-many class="Student"></one-to-many>
		</set>
	</class>	
	
</hibernate-mapping>


      配置了one-to-many会自动在t_student表中创建外键classid,与t_class的id映射。



      测试类【One2ManyTest

package com.bjpowernode.hibernate;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import junit.framework.TestCase;
import org.hibernate.Session;
import org.hibernate.Transaction;

public class One2ManyTest extends TestCase {
		
	public void testSave2() {
		Session session = null;
		try {
			session = HibernateUtils.getSession();
			session.beginTransaction();
			
			Student student1 = new Student();
			student1.setName("张三");
			//必须先将student1转化为Persistent状态,否则会抛TransientObjectException
			session.save(student1);
			
			Student student2 = new Student();
			student2.setName("李四");
			//必须先将student1转化为Persistent状态,否则会抛TransientObjectException
			session.save(student2);
			
			Class classes = new Class();
			classes.setName("提高班");
			
			Set<Student> students = new HashSet<Student> ();
			students.add(student1);
			students.add(student2);
			classes.setStudents(students);
			
			//可以成功保存数据。
			//先添加数据,将关系字段设置为null,再用update语句来更新关系字段
			//但是会发出多余的update语句来维持关系。
			session.save(classes);
			session.getTransaction().commit();
		 
		}catch(Exception e) {
			e.printStackTrace();
			session.getTransaction().rollback();
		}finally {
			HibernateUtils.closeSession(session);
		}
	}	

      结果图:



      执行测试前: ,执行测试后:

 

      虽然最后的结果跟多对一一样,但是根据sql语句,就可以看出,一对多是先添加student,classid为null,等添加了class以后,再执行update语句,把classid更新上去。这样同时可能会暴露一个问题:如果student的classid设置了not-null="true",则会抛PropertyValueException异常。所以不太推荐使用一对多。


      通过上面的例子,我们可以看出,其实一对多关联映射和多对一关联映射映射原理是一致的,都是在多的一端加入一个外键,指向一的一端。


      它们的区别在于维护的关系不同:

    • 多对一维护的关系是:多指向一的关系,有了此关系,在加载多的时候可以将一加载上来
    • 一对多维护的关系是:一指向多的关系,有了此关系,在加载一的时候可以将多加载上来

      在一的一端维护关系存在缺陷:

    • 因为多的一端Student不知道Class的存在(也就是Student没有维护与Class的关系)所以在保存Student的时候关系字段classid是为null的,如果将该关系字段设置为非空,则将无法保存数据
    • 另外因为Student不维护关系,而Class维护关系,Class就会发出多余的update语句,保证Class和Student有关系,这样加载Class的时候才可以把该Class对应的学生加载上来


目录
相关文章
|
Java 数据库连接 API
解锁高效开发秘籍:深入探究 Hibernate 如何优雅处理一对多与多对多关系,让数据映射再无烦恼!
【9月更文挑战第3天】Hibernate 是 Java 领域中最流行的 ORM 框架之一,广泛用于处理实体对象与数据库表之间的映射。尤其在处理复杂关系如一对多和多对多时,Hibernate 提供了丰富的 API 和配置选项。本文通过具体代码示例,展示如何使用 `@OneToMany`、`@JoinColumn`、`@ManyToMany` 和 `@JoinTable` 等注解优雅地实现这些关系,帮助开发者保持代码简洁的同时确保数据一致性。
321 4
|
Java 数据库连接 数据库
AI 时代风起云涌,Hibernate 实体映射引领数据库高效之路,最佳实践与陷阱全解析!
【8月更文挑战第31天】Hibernate 是一款强大的 Java 持久化框架,可将 Java 对象映射到关系数据库表中。本文通过代码示例详细介绍了 Hibernate 实体映射的最佳实践,包括合理使用关联映射(如 `@OneToMany` 和 `@ManyToOne`)以及正确处理继承关系(如单表继承)。此外,还探讨了常见陷阱,例如循环依赖可能导致的无限递归问题,并提供了使用 `@JsonIgnore` 等注解来避免此类问题的方法。通过遵循这些最佳实践,可以显著提升开发效率和数据库操作性能。
273 0
|
数据库 开发者 Java
Hibernate映射注解的魔力:实体类配置的革命,让你的代码量瞬间蒸发!
【8月更文挑战第31天】Hibernate 是一款出色的对象关系映射框架,简化了 Java 应用与数据库的交互。其映射注解让实体类配置变得直观简洁。本文深入剖析核心概念与使用技巧,通过示例展示如何简化配置。
217 0
|
Java 数据库连接 数据库
Hibernate5中实体映射命名策略
Hibernate5中实体映射命名策略
288 0
|
SQL 存储 Java
Hibernate - 继承关联关系映射
Hibernate - 继承关联关系映射
194 0
|
SQL 缓存 Java
框架分析(9)-Hibernate
框架分析(9)-Hibernate
|
缓存 Java 数据库连接
Hibernate:Java持久层框架的高效应用
通过上述步骤,可以在Java项目中高效应用Hibernate框架,实现对关系数据库的透明持久化管理。Hibernate提供的强大功能和灵活配置,使得开发者能够专注于业务逻辑的实现,而不必过多关注底层数据库操作。
198 1
|
SQL Java 数据库连接
Hibernate 是一款开源 ORM(对象关系映射)框架,封装了 JDBC,允许以面向对象的方式操作数据库,简化了数据访问层的开发。
Hibernate 是一款开源 ORM(对象关系映射)框架,封装了 JDBC,允许以面向对象的方式操作数据库,简化了数据访问层的开发。通过映射机制,它可以自动处理对象与数据库表之间的转换,支持主流数据库,提高了代码的可移植性和可维护性。其核心接口包括 SessionFactory、Session 和 Transaction 等,通过它们可以执行数据库的 CRUD 操作。配置方面,需在项目中引入 Hibernate 及数据库驱动依赖,并创建 `hibernate.cfg.xml` 配置文件来设置数据库连接和 Hibernate 行为参数。
212 1
|
SQL XML 存储
Hibernate框架【五】——基本映射——多对多映射
Hibernate框架【五】——基本映射——多对多映射
361 0
|
数据库 Java 数据库连接
Struts 2 与 Hibernate 的完美邂逅:如何无缝集成两大框架,轻松玩转高效 CRUD 操作?
【8月更文挑战第31天】本文通过具体示例介绍了如何在 Struts 2 中整合 Hibernate,实现基本的 CRUD 操作。首先创建 Maven 项目并添加相关依赖,接着配置 Hibernate 并定义实体类及其映射文件。然后创建 DAO 接口及实现类处理数据库操作,再通过 Struts 2 的 Action 类处理用户请求。最后配置 `struts.xml` 文件并创建 JSP 页面展示用户列表及编辑表单。此示例展示了如何配置和使用这两个框架,使代码更加模块化和可维护。
460 0