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


          在上一篇博客《一口一口吃掉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);
    		}
    	}	


          结果图:



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

     

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


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

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

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

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


  • 相关阅读:
    现阶段学习窘境总结(2013年6月21日-至今)
    MvcPager 分页控件
    JS 实现PDF文件打印
    json和Jsonp 使用总结(1)
    实战篇之存储过程的使用
    ASP.NET MVC5 之 客户端实现文件的下载
    WMI 技术
    PowerDesigner 的使用教程
    Rose
    对路径 obj 文件夹访问被拒绝
  • 原文地址:https://www.cnblogs.com/suncoolcat/p/3400436.html
Copyright © 2020-2023  润新知