【Java】Hibernate(六)关联映射之一对多

【一对多和多对一】

         一对多和多对一映射原理是一样的,都是在多的一端加入一个外键指向一的一端。区别就在于维护关系不同。
         多对一维护关系,多指向一,如果维护了多指向一的关系,加载多的时候把一也加载出来。
         一对多维护关系,一指向多,如果维护了一指向多的关系,加载一的时候会把多加载出来。

【单向】

         一个班级有多个学生,要想从班级得知学生,就是在一的这段维护关系,就要在一的这端用集合set,谁负责维护关系谁就来写外键。


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>


One2ManyTest代码:

public void testSave1(){//从一端保存
		Session session=null;
		try{
			session=HibernateUtils.getSession();
			session.beginTransaction();
			 
			Student student1=new Student();
			student1.setName("辛巴");
			session.save(student1);// persistent
			
			Student student2=new Student();
			student2.setName("彭彭");
			session.save(student2);// persistent
			
			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);
		}
	}

在一的这端维护关系存在缺陷:
         因为多的一端student不知道classes的存在,所以在保存student的时候关系字段classesid是为null的。如果将该关系字段设置为非空,则将无法保存数据。

         另外因为student不维护关系,而classes维护关系,classes就会发出多余的update语句,为保证classes和student有关系,这样加载classes的时候才可以把该classes对应的学生加载上来。


【双向】

         一对多关联都应设为双向,采用一对多双向关联映射的目的,主要是为了解决一对多单向关联的缺陷,而并不是需求驱动。



         我们需要让student,也就是“多”的这一端维护关系,为了让“一”的这端失效,我们需要设置映射属性 inverse ,设为true就是让对端负责更新。如果从一的这端保存,维护关系的字段就为空,所以我们只能从多端保存。

 一对多双向关联的映射方式:
*在一的一端集合上采用<key>标签,在多的一端加入一个外键
*在多的一端采用<many-to-one>标签
*key标签和many to one标签加入的字段保持一致,否则会产生数据混乱


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" inverse="true">
	        <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"/>
		<many-to-one name="classes" column="classesid"/>
	</class>
</hibernate-mapping>




One2ManyTest代码:
public void testSave2(){//从多端保存
		Session session=null;
		try{
			session=HibernateUtils.getSession();
			session.beginTransaction();
			 
			Classes classes=new Classes();
			classes.setName("一班");
			session.save(classes);
			
			Student student1=new Student();
			student1.setName("辛巴");
			student1.setClasses(classes);
			session.save(student1);// persistent
			
			Student student2=new Student();
			student2.setName("彭彭");
			student2.setClasses(classes);
			session.save(student2);// persistent
			
		
		
			session.getTransaction().commit();
			
		}catch(Exception e){
			e.printStackTrace();
			session.getTransaction().rollback();
			
		}finally{
			HibernateUtils.closeSession(session);
		}
	}
    

【Inverse和级联】

         级联是连锁性操作,是操作上的连锁反应,对增加删除修改起作用,不影响查询。inverse影响的是存储方向,是控制方向上的翻转,只影响存储,不影响加载。
        inverse属性可以用在一对多、多对多双向关联上,inverse属性默认为false,为false表示本端可以维护关系。true表示本端不能维护,交给另一端维护关系,本端失效。
         所以一对多关联映射,我们通常在多的一端维护关系,让一的一端失效,设置inverse为true。

【小结】

         一对多是比较常用的关联映射,要注意双向是为了避免单向的缺陷,并不是由需求驱动。下篇多对一映射见。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值