`

hibernate 一对多(one-to-many)双向关联

 
阅读更多

一对多(one-to-many)双向关联实例(Department- Employee)

这里的一对多双向关联是在域模型(实体对象模型)上的概念,在关系数据库中,只存在外键参照关系,而且总是由"many"方参照"one"方,因为这样才能消除冗余数据,因上关系数据库实际上只支持多对一或一对一的单向关联.在实体(类与类之间)各种各样的关系中,数多对一的的单向关联关系与数据库中的外键参照关系最匹配了.

在我的前一篇文章多对一的基础上进行修改。

1.修改Department实体类:

Java代码 复制代码 收藏代码
  1. package com.reiyen.hibernate.domain   
  2. public class Department {   
  3.   
  4.     private int id;   
  5.     private String name;   
  6.     private Set<Employee> emps;    
  7.   
  8.    //setter和getter方法   
  9. }  
package com.reiyen.hibernate.domain
public class Department {

	private int id;
	private String name;
	private Set<Employee> emps; 

   //setter和getter方法
}

 2.修改Department.hbm.xml文件:

Xml代码 复制代码 收藏代码
  1. <?xml version="1.0"?>  
  2. <!DOCTYPE hibernate-mapping PUBLIC    
  3.     "-//Hibernate/Hibernate Mapping DTD 3.0//EN"   
  4.     "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
  5. <hibernate-mapping package="com.reiyen.hibernate.domain">  
  6.     <class name="Department" >  
  7.         <id name="id" >  
  8.             <generator class="native" />  
  9.         </id>  
  10.         <property name="name" />  
  11.         <set name="emps">  
  12.         <key column="depart_id" />  
  13.         <one-to-many class="Employee"/>  
  14.         </set>  
  15.     </class>  
  16. </hibernate-mapping>  
<?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.reiyen.hibernate.domain">
	<class name="Department" >
		<id name="id" >
			<generator class="native" />
		</id>
		<property name="name" />
		<set name="emps">
		<key column="depart_id" />
		<one-to-many class="Employee"/>
		</set>
	</class>
</hibernate-mapping>

<set>元素的属性name:设定待映射的持久化类的属性名,这里为Depatment类的emps属性.

<set>元素的两个子元素:

<key>:设定与所关联的持久化类对应的表的外键,此处为Employee表的depart_id字段.

<one-to-many>:设定所关联的持久化类,此处为Employee.

Hibernate根椐以上配置信息获得如下信息:

<set>元素表明Department类的emps属性为java.util.Set集合类型.

<class>子元素表明emps集合中存放的是一组Employee对象

<key>子元素表明employee表是通过外键depart_id参照department表的.

 

 3. 其余的保持原样,测试类如下:

Java代码 复制代码 收藏代码
  1. public class Many2One {   
  2.   
  3.     /**  
  4.      * @param args  
  5.      */  
  6.     public static void main(String[] args) {   
  7.         Department depart = add();   
  8.         Department department = queryDepart(depart.getId());   
  9.                 //department.getEmps();3   
  10. // System.out.println("emp size:" + department.getEmps().size());4     
  11.     }   
  12.   
  13.     static Department queryDepart(int departId) {   
  14.         Session s = null;   
  15.         Transaction tx = null;   
  16.         try {   
  17.             s = HibernateUtil.getSession();   
  18.             tx = s.beginTransaction();   
  19.             Department depart = (Department) s.get(Department.class, departId);   
  20.              System.out.println("emp size:" + depart.getEmps().size());//1         
  21.                          // System.out.println("emps class:" + depart.getEmps().getClass());   //2    
  22.                          // Hibernate.initialize(depart.getEmps());   
  23.             tx.commit();   
  24.             return depart;   
  25.         } finally {   
  26.             if (s != null)   
  27.                 s.close();   
  28.         }   
  29.     }   
  30.   
  31.     static Department add() {   
  32.         Session s = null;   
  33.         Transaction tx = null;   
  34.         try {   
  35.             Department depart = new Department();   
  36.             depart.setName("department name");   
  37.                
  38.             Employee employee1 = new Employee();   
  39.             employee1.setDepartment(depart); // 对象模型:建立两个对象的关联    
  40.             employee1.setName("employee1 name2");   
  41.                
  42.             Employee employee2 = new Employee();   
  43.             employee2.setDepartment(depart); // 对象模型:建立两个对象的关联    
  44.             employee2.setName("employee2 name2");   
  45.   
  46.        // Set<Employee> set = new HashSet<Employee>();   
  47.             //    set.add(employee1);   
  48.             //  set.add(employee2);   
  49.             //  depart.setEmps(set);   
  50.                
  51.             s = HibernateUtil.getSession();   
  52.             tx = s.beginTransaction();   
  53.             s.save(depart);   
  54.             s.save(employee1);   
  55.             s.save(employee2);   
  56.             tx.commit();   
  57.             return depart;   
  58.         } finally {   
  59.             if (s != null)   
  60.                 s.close();   
  61.         }   
  62.     }   
  63. }  
public class Many2One {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Department depart = add();
		Department department = queryDepart(depart.getId());
                //department.getEmps();3
// System.out.println("emp size:" + department.getEmps().size());4  
	}

	static Department queryDepart(int departId) {
		Session s = null;
		Transaction tx = null;
		try {
			s = HibernateUtil.getSession();
			tx = s.beginTransaction();
			Department depart = (Department) s.get(Department.class, departId);
			 System.out.println("emp size:" + depart.getEmps().size());//1      
                         // System.out.println("emps class:" + depart.getEmps().getClass());   //2 
                         // Hibernate.initialize(depart.getEmps());
			tx.commit();
			return depart;
		} finally {
			if (s != null)
				s.close();
		}
	}

	static Department add() {
		Session s = null;
		Transaction tx = null;
		try {
			Department depart = new Department();
			depart.setName("department name");
			
			Employee employee1 = new Employee();
			employee1.setDepartment(depart); // 对象模型:建立两个对象的关联 
			employee1.setName("employee1 name2");
			
			Employee employee2 = new Employee();
			employee2.setDepartment(depart); // 对象模型:建立两个对象的关联 
			employee2.setName("employee2 name2");

       // Set<Employee> set = new HashSet<Employee>();
		    //    set.add(employee1);
		    //	set.add(employee2);
		    //	depart.setEmps(set);
			
			s = HibernateUtil.getSession();
			tx = s.beginTransaction();
			s.save(depart);
			s.save(employee1);
			s.save(employee2);
			tx.commit();
			return depart;
		} finally {
			if (s != null)
				s.close();
		}
	}
}

 控制台打印信息如下:

Hibernate: insert into Department (name) values (?)
Hibernate: insert into Employee (name, depart_id) values (?, ?)
Hibernate: insert into Employee (name, depart_id) values (?, ?)
Hibernate: select department0_.id as id1_0_, department0_.name as name1_0_ from Department department0_ where department0_.id=?
Hibernate: select emps0_.depart_id as depart3_1_, emps0_.id as id1_, emps0_.id as id2_0_, emps0_.name as name2_0_, emps0_.depart_id as depart3_2_0_ from Employee emps0_ where emps0_.depart_id=?

emp size:2

数据库中记录如下所示:

mysql> select * from employee;
+----+-----------------+-----------+
| id | name            | depart_id |
+----+-----------------+-----------+
|  1 | employee1 name2 |         1 |
|  2 | employee2 name2 |         1 |
+----+-----------------+-----------+
2 rows in set (0.00 sec)

mysql> select * from department;
+----+-----------------+
| id | name            |
+----+-----------------+
|  1 | department name |
+----+-----------------+
1 row in set (0.00 sec)

 

虽然对象模型修改了,但数据库关系模型并没有改变。

 

如果把测试程序中注释部分去掉,同时将注释为“建立对象模型”这两句程序注释掉,虽然也能正确运行,但控制台会多打印出两条更新语句,说明数据库多执行了两次更新操作,效率上有影响,如下所示:

Hibernate: insert into Department (name) values (?)
Hibernate: insert into Employee (name, depart_id) values (?, ?)
Hibernate: insert into Employee (name, depart_id) values (?, ?)
Hibernate: update Employee set depart_id=? where id=?
Hibernate: update Employee set depart_id=? where id=?

Hibernate: select department0_.id as id1_0_, department0_.name as name1_0_ from Department department0_ where department0_.id=?
Hibernate: select emps0_.depart_id as depart3_1_, emps0_.id as id1_, emps0_.id as id2_0_, emps0_.name as name2_0_, emps0_.depart_id as depart3_2_0_ from Employee emps0_ where emps0_.depart_id=?
emp size:2

 

4.懒加载分析:

(1)如果将程序中标记为1的程序注释掉,控制台打印信息如下:

Hibernate: select department0_.id as id0_0_, department0_.name as name0_0_ from Department department0_ where department0_.id=?

此时只是将Department对象查询出来了,而对应的Employee并没有进行查询。

(2)如果将程序中标记为1的程序注释掉,同时将标记为2的前面的注释去掉,运行程序,控制台打印信息如下:

Hibernate: select department0_.id as id0_0_, department0_.name as name0_0_ from Department department0_ where department0_.id=?
emps class:class org.hibernate.collection.PersistentSet

此时可以看到其实Hibernate将hashset替换成了它自己写的PersistentSet,所以才能实现懒加载功能。同时可以发现当调用department.getEmps();hibernate只是获取了集合代理对象的引用,它并没有去查询数据库来填充集合对象。你还可以进一步测试来验证这个问题。如果你 将程序中标记为1的程序注释掉,同时去掉标记为3的语句前面的注释,你会发现程序能正常运行,但如果去掉标记为4的语句前面的注释,运行程序,则会抛出如下异常:

 org.hibernate.LazyInitializationException : failed to lazily initialize a collection of role: com.reiyen.hibernate.domain.Department.emps, no session or session was closed

(3)当进行department对象查询时,从department的表结构中也不能判断这个Department对象是否有对应的Employee,那为什么它不像一对一查询时,也一次性把相关联的对象查询出来呢??这是因为如果将关联的对象查询出来的话,因为数据较多,它会严重影响效率,而不像一对一时,反正从对象只有一个,一次性查询出来影响也不是太大,所以hibernate就假定你有相对应的Employee,直接创建了一个集合代理对象的返回给你(把对象引用先给你),等你需要数据的时候再去查询数据库,以提高效率!

分享到:
评论

相关推荐

    Hibernate one-to-many / many-to-one关系映射

    一、一对一(one-to-one)与一对多(one-to-many)关系 1. 一对一关系: 在现实世界中,如一个人只有一个身份证,这就是典型的"一对一"关系。在Hibernate中,可以通过@OneToOne注解实现。这种关系通常需要使用外键...

    hibernate学习5之one-to-many双向关联.docx

    在配置双向一对多关联时,我们通常在"多"一端(这里是`Student`)的集合属性上使用`&lt;many-to-one&gt;`标签,将`Classes`对象映射到数据库中的外键。同时,在"一"端(`Classes`)使用`&lt;set&gt;`标签,表示班级可以包含多个...

    (4)Hibernate中的many-to-one和one-to-many关系

    本话题主要探讨两种基本的关系映射类型:many-to-one(多对一)和one-to-many(一对多)。这两种关系映射是数据库中常见的关联类型,理解和掌握它们对于开发高质量的Java应用至关重要。 1. many-to-one关系 many-to...

    hibernate one-to-one 一对一唯一外键关联映射_单向 and 双向

    在本文中,我们将详细介绍Hibernate一对一唯一外键关联映射的概念、配置方法和实践应用。 一对一唯一外键关联映射的概念 在Hibernate中,一对一唯一外键关联映射是指两个实体之间的关联关系,其中一个实体作为外键...

    hibernate one-to-many 单/双向关联映射配置心得

    本文主要关注Hibernate中的一个核心概念——一对一(One-to-One)、一对多(One-to-Many)和多对一(Many-to-One)关联映射,特别是关于“一到多”单向和双向关联映射的配置心得。 首先,让我们了解“一到多”关联...

    Hibernate one-to-many-annotation

    在Hibernate中,`one-to-many`关系是常见的实体间关系之一,表示一个实体可以与多个其他实体相关联。本文将深入探讨`Hibernate one-to-many`注解的使用和实现细节。 ### 一、`@OneToMany`注解概述 `@OneToMany`...

    hibernate一对多,多对一,一对多双向关联

    标题"hibernate一对多,多对一,一对多双向关联"指涉的是Hibernate框架中常见的关系映射概念。在数据库设计中,实体间的关系通常包括一对一(One-to-One)、一对多(One-to-Many)和多对一(Many-to-One)关系,而在...

    Hibernate一对多(多对一)双向关联(annotation/xml)

    在Java的持久化框架Hibernate中,一对多(Many-to-One)和多对一(One-to-Many)的关系映射是数据库关系模型中的常见关联类型。本文将深入探讨这两种关联方式在使用Hibernate时的配置,包括基于注解(Annotation)和...

    hibernate双向一对多关联映射(XML)

    总结起来,Hibernate的双向一对多关联映射(XML)涉及的主要知识点包括:实体类的关联、`&lt;set&gt;`和`&lt;one-to-many&gt;`标签的使用、`&lt;many-to-one&gt;`标签的使用、以及如何在Java代码中维护这种关联。理解并熟练运用这些...

    hibernate一对一关联关系

    在实体类之间,Hibernate支持多种关联关系,包括一对一(One-to-One)、一对多(One-to-Many)和多对多(Many-to-Many)。本资源主要探讨的是“hibernate一对一关联关系”。 一对一关联关系在现实世界中很常见,...

    hibernate的关联映射

    关联映射主要包括四种类型:一对一(One-to-One)、一对多(One-to-Many)、多对一(Many-to-One)和多对多(Many-to-Many)。下面我们将逐一探讨这些关联映射的配置方法。 1. **一对一关联映射** - **主键关联**...

    hibernate一对多双向

    在探讨“Hibernate一对多双向”这一主题时,我们首先需要理解Hibernate框架以及它在Java开发中的重要性。Hibernate是一个开放源代码的对象关系映射(ORM)框架,它为Java应用程序提供了一种将对象模型与数据库模型相...

    hibernate一对多关联映射(双向关联)

    在Hibernate的一对多关联中,双向关联意味着双方都可以通过导航属性访问对方。例如,用户类(User)可以有一个订单集合(Orders),而订单类(Order)同样有一个用户属性(User)。这样设计的好处在于,我们可以在任一侧轻松...

    Hibernate之第3解之-hibernate_hibernate_many2one_1

    Many-to-One关系是现实世界中常见的关联类型,一个实体可能对应另一个实体的多个实例,例如,一个员工可以属于一个部门,但一个部门可能有多个员工。在Hibernate中,Many-to-One关系通过配置实现,主要涉及以下几点...

    Hibernate关联映射

    9. Hibernate 一对一外键双向关联、主键双向关联、连接表双向关联、一对多外键双向关联、一对多连接表双向关联、多对多双向关联: 这些关联方式与单向关联类似,区别在于两个实体类都知道彼此的关联。在双向关联中...

    hibernate实例(一对多,多对一)

    在这个“hibernate实例(一对多,多对一)”的主题中,我们将深入探讨两种重要的关联关系:一对一(One-to-One)和一对多(One-to-Many)。 **一对一关联(One-to-One)** 在一对一关联中,一个实体与另一个实体之间...

    hibernate 映射-一对多双向

    3. **一对多关联(One-to-Many Association)**:使用`@OneToMany`注解在父类(拥有多个子项的一方)中声明,表示一个实体可以与多个其他实体相关联。可以通过`mappedBy`属性指定关联的另一端。 4. **多对一关联...

    Hibernate性能调优

    - `many-to-one`关联可以用来表达多种类型的关系,包括一对一、一对多和多对一。 - 双向`many-to-one`关联的例子,比如麻将桌上的玩家位置与玩家之间的关系。 #### 三、`one-to-one`关联管理 `one-to-one`关联...

    hibernate_1700_one2many_many2one_bi_crud(5)

    标题中的“hibernate_1700_one2many_many2one_bi_crud(5)”指的是一项关于Hibernate框架的教程,重点在于介绍一对多(One-to-Many)和多对一(Many-to-One)双向关联关系的创建、读取、更新和删除(CRUD)操作。...

Global site tag (gtag.js) - Google Analytics