`
yxwang0615
  • 浏览: 560908 次
  • 性别: Icon_minigender_1
  • 来自: 青岛
社区版块
存档分类
最新评论

hibernate3.2(八)一对多关联映射

 
阅读更多

在数据库设计方面,一对多关系关联和多对一关联关系是一样的,都是在多的一方维护关联关系,即在多的一方添加一个外键指向一的那一端(一般指向的是主键),我们不能在一的一方添加集合表示多的一方,这样也不符合数据库的设计范式。

 

数据库对应的实体类的关联关系的设计:

假设A关联B,A对B有依赖关系,就在A的一方添加对B的引用(即在A中添加一个关联字段关联B)。关联关系的命名一般都是把被依赖的一方放在后面表示。如A和B之间的关系是一对多的关联关系,那么就说A(一得一方)依赖了B(多的一方),要在A中添加关联字段关联B。一对多关联映射是在A中添加一个set集合关联B。

 

 一、单向一对多关联映射示例,班级关联学生:

public class Student {
	private int studentid;
	private String name;
	
                getter & setter...	
}

 

 

public class Classes {
	
	private int classid;
	private String name;
	private Set studets;//班级关联学生的关联关系属性
	
                getter & setter....
	
}

 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 package="com.wyx.hibernate">
	<class name="Classes" table="t_classes">
		<id name="classid">
			<generator class="native"/>
		</id>
		<property name="name"/>
		<set name="students">
			<key column="classid"/><!-- 创建一列classid字段加到student表中 -->
			<one-to-many class="Student"/><!-- 拿classid作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.wyx.hibernate.Student" table="t_student">
		<id name="studentid">
			<generator  class="native"/>
		</id>
		<property name="name"/>
	</class>
</hibernate-mapping>

测试save方法,从classes端保存: 

public void testSave(){
		Session session = HibernateUtils.getSession();
		try {
			session.beginTransaction();
			
			Student student1 = new Student();
			student1.setName("菜10");
			//session.save(student1);
			Student student2 = new Student();
			student2.setName("虫虫");
			//session.save(student2);
			

			Set students = new HashSet<Student>();
			students.add(student1);
			students.add(student2);
			
			Classes classes = new Classes();
			classes.setName("BDQN_T32");
			classes.setStudents(students);
			session.save(classes);
			session.getTransaction().commit();
		} catch (HibernateException e) {
			e.printStackTrace();
			session.getTransaction().rollback();
		}finally{
			HibernateUtils.closeSession(session);
		}
		
	}

 

注释部分打开才不报错,控制台输出:

Hibernate: insert into t_student (name) values (?)
Hibernate: insert into t_student (name) values (?)
Hibernate: insert into t_classes (name) values (?)
Hibernate: update t_student set classid=? where studentid=?
Hibernate: update t_student set classid=? where studentid=?

可见原理是先在student表插入数据,但关联字段classid的值为null,因为此时student是被关联的一方,student不知道有class。class是一的一方,在这里是依赖方,需要维护表之间的关联关系,classes表插入数据时,就去修改student的classid,为student添加了关联管。

 

测试load方法,从clssses端取出student 的信息:

 

public void testSLoad(){
		Session session = HibernateUtils.getSession();
		try {
			session.beginTransaction();
			Classes classes = (Classes)session.load(Classes.class, 1);
			System.out.println("classes.name = "+ classes.getName());
			Set<Student> students = classes.getStudents();
			for(Iterator<Student> iter = students.iterator();iter.hasNext();){
				Student student = iter.next();
				System.out.println("classes.student.name = " + student.getName());
			}
			System.out.println("");
			session.getTransaction().commit();
		} catch (HibernateException e) {
			e.printStackTrace();
			session.getTransaction().rollback();
		}finally{
			HibernateUtils.closeSession(session);
		}
		
	}

 控制台输出:

Hibernate: select classes0_.classid as classid0_0_, classes0_.name as name0_0_ from t_classes classes0_ where classes0_.classid=?
classes.name = BDQN_T32
Hibernate: select students0_.classid as classid1_, students0_.studentid as studentid1_, students0_.studentid as studentid1_0_, students0_.name as name1_0_ from t_student students0_ where students0_.classid=?
classes.student.name = 菜10
classes.student.name = 虫虫

单向一对多映射的缺点:

1. 如果将student表的classid设置为非空限制,则无法保存。

2. 因为不是在sutdent端维护关系,所以student不知道是哪个classes的,所以需要发出多余的update语句更新关系。

所以单向一对多用的很少,最好设计成双向一对多的,把关系维护交给多的一方去处理会比较简单。

二、双向一对多关联映射示例,班级学生互相关联:

要使加载student也能够加载班级,所以在单向一对多关系映射的基础上,这样classes实体中有Set students,又在student实体中加入了一个classes字段,完成了双向关联。

 classes.hbm.xml不变,下面是修改过的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.wyx.hibernate.Student" table="t_student">
		<id name="studentid">
			<generator  class="native"/>
		</id>
		<property name="name"/>
		<!-- column一定要和classes.hbm.xml中的key 下的 column一致,否则classid和classes字段都会生成 -->
		<many-to-one name="Classes" not-null="true" column="classid"/>
	</class>
</hibernate-mapping>

 测试save方法:

public void testSave(){
		Session session = HibernateUtils.getSession();
		try {
			session.beginTransaction();
			
			Classes classes = new Classes();
			classes.setName("BDQN_T32");
			session.save(classes);//transient状态如果不保存就用会报错
			
			Student student1 = new Student();
			student1.setName("菜10");
			student1.setClasses(classes);
			Student student2 = new Student();
			student2.setClasses(classes);
			student2.setName("虫虫");
			
			session.save(student1);
			session.save(student2);
			
			session.getTransaction().commit();
		} catch (HibernateException e) {
			e.printStackTrace();
			session.getTransaction().rollback();
		}finally{
			HibernateUtils.closeSession(session);
		}
		
	}

 打印结果:

Hibernate: insert into t_classes (name) values (?)
Hibernate: insert into t_student (name, classid) values (?, ?)
Hibernate: insert into t_student (name, classid) values (?, ?)

 

 测试load方法:

public void testLoad(){
		Session session = HibernateUtils.getSession();
		try {
			session.beginTransaction();
			Query query = session.createQuery("from Student");
			
			for(Iterator<Student> iter = query.iterate();iter.hasNext();){
				Student stu = iter.next();
				System.out.println("student.name = " + stu.getName() + " student.classes = " + stu.getClasses().getName());
			}
			Student student = (Student)session.load(Student.class, 1);
			session.getTransaction().commit();
		} catch (HibernateException e) {
			e.printStackTrace();
			session.getTransaction().rollback();
		}finally{
			HibernateUtils.closeSession(session);
		}
		
	}

 

打印输出:

Hibernate: select student0_.studentid as col_0_0_ from t_student student0_
Hibernate: select student0_.studentid as studentid1_0_, student0_.name as name1_0_, student0_.classid as classid1_0_ from t_student student0_ where student0_.studentid=?
Hibernate: select classes0_.classid as classid0_0_, classes0_.name as name0_0_ from t_classes classes0_ where classes0_.classid=?
student.name = 菜10 student.classes = BDQN_T32
Hibernate: select student0_.studentid as studentid1_0_, student0_.name as name1_0_, student0_.classid as classid1_0_ from t_student student0_ where student0_.studentid=?
student.name = 虫虫 student.classes = BDQN_T32

 

总结:通常采用一对多关联映射,都是在多的一段维护关联关系,一的一端让他失效。只需要在classes.hbm的set集合里加入inverse="true"的属性(反转)。

<set name="students" inverse="true" cascade="all">
			<key column="classid"/><!-- 创建一列classid字段加到student表中 -->
			<one-to-many class="Student"/><!-- 拿classid作student的外键 -->
		</set>

 

 现在再从一的一方save一个classes,调用上面单向一对多关联映射的testSave方法,注释部分就不要打开了,不然保存classes的时候还是要发update,会修改student。

这里set标签下还有了cascade ="all" ,级联操作。得到的打印结果:

Hibernate: insert into t_classes (name) values (?)
Hibernate: insert into t_student (name, classid) values (?, ?)
Hibernate: insert into t_student (name, classid) values (?, ?)
这样不管从那边存,sql打印效果都一样了,hibernate为我们做了反转。

 

测试load,从classes中打印student的name:

public void testInverseLoad(){
		Session session = HibernateUtils.getSession();
		try {
			session.beginTransaction();
			Classes classes = (Classes)session.load(Classes.class, 2);
			for(Iterator<Student> iter = classes.getStudents().iterator();iter.hasNext();){
				Student stu = iter.next();
				System.out.println("classes.student.name = " + stu.getName());
			}
			session.getTransaction().commit();
		} catch (HibernateException e) {
			e.printStackTrace();
			session.getTransaction().rollback();
		}finally{
			HibernateUtils.closeSession(session);
		}
		
	}

 Hibernate: select classes0_.classid as classid0_0_, classes0_.name as name0_0_ from t_classes classes0_ where classes0_.classid=?
Hibernate: select students0_.classid as classid1_, students0_.studentid as studentid1_, students0_.studentid as studentid1_0_, students0_.name as name1_0_, students0_.classid as classid1_0_ from t_student students0_ where students0_.classid=?
classes.student.name = liwei
classes.student.name = 张三1

 

测试load,从student中取classes的name:

public void testLoad1(){
		Session session = HibernateUtils.getSession();
		try {
			session.beginTransaction();
			Student stu = (Student)session.load(Student.class, 1);
			System.out.println("student.class.name = " + stu.getClasses().getName());
			session.getTransaction().commit();
		} catch (HibernateException e) {
			e.printStackTrace();
			session.getTransaction().rollback();
		}finally{
			HibernateUtils.closeSession(session);
		}
		
	}

 Hibernate: select student0_.studentid as studentid1_0_, student0_.name as name1_0_, student0_.classid as classid1_0_ from t_student student0_ where student0_.studentid=?
Hibernate: select classes0_.classid as classid0_0_, classes0_.name as name0_0_ from t_classes classes0_ where classes0_.classid=?
student.class.name = BDQN_T33

分享到:
评论

相关推荐

    hibernate3.2(六)多对一关联映射

    在本篇关于“Hibernate3.2(六)多对一关联映射”的主题中,我们将深入探讨在Java Persistence API(JPA)框架下,如何利用Hibernate实现多对一的关联映射。Hibernate作为JPA的一个实现,是Java开发中常用的ORM...

    开发框架 hibernate3.2

    6. **一对多、多对一、一对一关联映射** - 通过@ManyToOne、@OneToMany、@OneToOne注解定义不同类型的关联关系,简化了数据间的关联操作。 7. **延迟加载(Lazy Loading)** - Hibernate支持属性和关联的懒加载,...

    hibernate3.2

    10. **集合映射**:在Hibernate 3.2中,可以映射各种类型的集合,如List、Set、Map等,同时支持一对多、多对一、一对一等多种关联关系。 11. **延迟加载(Lazy Loading)**:为了解决性能问题,Hibernate 提供了懒...

    hibernate3.2lib及源码jar包纯净版

    6. **关联映射**:支持一对一、一对多、多对一、多对多等多种关联关系的映射。 在使用这两个JAR文件时,开发者需要确保有相应的JDBC驱动以连接数据库,并配置Hibernate的配置文件(如hibernate.cfg.xml),定义...

    Hibernate3.2官方中文参考手册 高清晰 pdf

    - **一对多映射**:处理实体间的多对一或多对多关系。 - **继承映射**:支持不同类型的继承关系映射到数据库。 #### 六、查询语言 - **HQL (Hibernate Query Language)**:面向对象的查询语言,类似于 SQL 但更...

    hibernate_3.2官方开发包

    11. **Association Mapping关联映射**:Hibernate支持一对一、一对多、多对一、多对多等各种关联映射,方便地处理复杂的对象关系。 12. **延迟加载Lazy Loading**:Hibernate的懒加载机制可以推迟到真正需要时才...

    Hibernate3.2官方中文参考手册.pdf+Hibernate.pdf(Hibernate的学习资料)

    5. **关系映射(Relationship Mapping)**:包括一对一(OneToOne)、一对多(OneToMany)、多对一(ManyToOne)和多对多(ManyToMany)关系。理解这些关系的配置和使用是掌握Hibernate的关键。 6. **会话(Session...

    hibernate3.2用到的jar包

    11. **关联映射**:Hibernate 支持一对一、一对多、多对一和多对多的关系映射,通过注解或XML配置来定义实体之间的关联。 12. **延迟加载(Lazy Loading)**:为了优化性能,Hibernate 实现了延迟加载机制。默认...

    hibernate3.2 源码

    9. **集合映射**:在实体类中,可以定义一对多、一对一、多对一、多对多的关系。Hibernate提供了丰富的集合类型(如List、Set、Map等)来映射这些关系。 10. **延迟加载(Lazy Loading)**:为了提高性能,...

    hibernate一对多关联映射

    在Java的持久化框架Hibernate中,一对多关联映射是一种常见的关系数据库模型,它用于表示一个实体(类)可以与多个其他实体实例相关联的情况。本文将深入探讨Hibernate中的一对多关联映射,以及如何实现双向关联。 ...

    hibernate3.2级联关系自身一对多双向关联

    在Hibernate 3.2版本中,级联关系是处理对象间关联的重要特性,特别是自身一对多双向关联,这允许一个实体类实例与多个相同类型的其他实例相关联,而且这种关联是双向的。现在,让我们深入探讨这个主题。 首先,...

    hibernate3.2源码

    9. **关联映射**:包括一对一(@OneToOne)、一对多(@OneToMany)、多对一(@ManyToOne)和多对多(@ManyToMany)等关系映射,以及懒加载和立即加载策略。 10. **类型系统和用户类型**:Hibernate支持多种内置类型...

    hibernate3.2参考文档

    3. **实体映射**:讲解如何使用Hibernate的XML映射文件(.hbm.xml)或注解来定义Java类与数据库表之间的映射关系,包括字段映射、主键生成策略、关联映射(一对一、一对多、多对一、多对多)等。 4. **Session接口*...

    Hibernate一对多主键关联映射源代码

    首先,我们需要理解一对多关联的基本概念。在数据库中,一个表的某一列(主键)可能与另一个表的多行相关联,比如一个学生可以有多门课程,而一门课程可以被多个学生选修。在Hibernate中,我们通过配置XML映射文件或...

    hibernate-3.2 源码

    3. 集合映射:一对多、多对多关系的映射,如Set、List、Map等集合类型的处理。 4. 异步查询:通过Hibernate的FutureResult和Query.listAsync()实现异步数据检索。 5. 动态模型:无需预先定义实体类,可以动态构建...

    Hibernate\hibernate3.2官方中文参考手册PDF

    5. **关联映射**:Hibernate支持多种对象之间的关联映射,包括一对一、一对多、多对一、多对多关系。这些关联可以在配置文件中定义,或者使用JPA注解来声明。 6. **集合映射**:在处理一对多、多对多关联时,...

    hibernate3.2API

    5. **关联映射**:包括一对一(OneToOne)、一对多(OneToMany)、多对一(ManyToOne)、多对多(ManyToMany)等关系的映射,通过`@OneToOne`、`@OneToMany`等注解实现。 6. **事件监听**:Hibernate允许注册监听器...

    hibernate3.2 开发API+源码参考

    Hibernate3.2是其一个重要版本,它带来了许多改进和新特性,包括性能优化、对JPA的支持以及更多的查询选项。 ### Hibernate3.2 API `hibernate3.2API`是指Hibernate 3.2版本的官方API文档。这个文档详细介绍了各种...

    Hibernate3.2.zip

    5. **Association Mapping**:Hibernate 支持多种关联映射,如一对一(OneToOne)、一对多(OneToMany)、多对一(ManyToOne)、多对多(ManyToMany)。这些映射方式允许对象之间的复杂关系在数据库中得以体现。 6....

    hibernate3.2中文文档

    2. **一对多(OneToMany)**:一个实体类可以拥有多个其他实体类实例,通过@OneToMany注解定义。 3. **多对一(ManyToOne)**:多个实体类实例对应一个实体类,使用@ManyToOne注解。 4. **多对多(ManyToMany)**:...

Global site tag (gtag.js) - Google Analytics