【HIbernate框架学习】:Hibernate对象关系映射之单向多对一关联映射

       单向多对一关联映射

       我们先来假设一个场景,从学生的角度看,学生和班级的关系就是多对一的关系,也就是多个学生属于一个班

级。多对一关联映射原理就是在多的一端加入一个外键,指向一的一端;在多的一端采用<many-to-one>标签映

射,也就是在Students.hbm.xml对象关系映射配置文件中采用,单向多对一关联映射是在多的一端来维护关联字

段,在我们这个例子中也就是在学生一端来维护关系字段。

       如下图所示(图中关系表示多个用户属于一个组):

      

       Student实体类:

package com.demo.entity;

import java.io.Serializable;

@SuppressWarnings("serial")
public class Student implements Serializable {
	private int sid;
	private String sname;
	private String sex;
	//在多方定义一个一方的引用
	private Grade grade;

	public int getSid() {
		return sid;
	}

	public void setSid(int sid) {
		this.sid = sid;
	}

	public String getSname() {
		return sname;
	}

	public void setSname(String sname) {
		this.sname = sname;
	}

	public String getSex() {
		return sex;
	}

	public void setSex(String sex) {
		this.sex = sex;
	}

	public Grade getGrade() {
		return grade;
	}

	public void setGrade(Grade grade) {
		this.grade = grade;
	}

	public Student() {
		super();
	}

	public Student(String sname, String sex) {
		super();
		this.sname = sname;
		this.sex = sex;
	}

}

       Student对象关系映射配置文件:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC 
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
	<class name="com.demo.entity.Student" table="t1_student">
		<id name="sid" column="sid" type="java.lang.Integer">
			<generator class="increment"></generator>
		</id>
		<property name="sname" type="java.lang.String">
			<column name="sname" length="20" not-null="true"></column>
		</property>
		<property name="sex">
			<column name="sex"></column>
		</property>	
		
		<!-- 配置单向多对一关联关系 -->
		<many-to-one name="grade" class="com.demo.entity.Grade" column="gid"></many-to-one>
	
	</class>
</hibernate-mapping>

      Grade实体类:

package com.demo.entity;

import java.io.Serializable;

@SuppressWarnings("serial")
public class Grade implements Serializable {
	private int gid;
	private String gname;
	private String gdesc;

	public int getGid() {
		return gid;
	}

	public void setGid(int gid) {
		this.gid = gid;
	}

	public String getGname() {
		return gname;
	}

	public void setGname(String gname) {
		this.gname = gname;
	}

	public String getGdesc() {
		return gdesc;
	}

	public void setGdesc(String gdesc) {
		this.gdesc = gdesc;
	}

	public Grade() {
		super();
	}

	public Grade(int gid, String gname, String gdesc) {
		super();
		this.gid = gid;
		this.gname = gname;
		this.gdesc = gdesc;
	}

	public Grade(String gname, String gdesc) {
		super();
		this.gname = gname;
		this.gdesc = gdesc;
	}

}

      Grade对象关系映射配置文件:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC 
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
	<class name="com.demo.entity.Grade" table="t1_grade">
		<id name="gid" column="gid" type="java.lang.Integer">
			<generator class="increment"></generator>
		</id>
		<property name="gname" type="java.lang.String">
			<column name="gname" length="20" not-null="true"></column>
		</property>
		<property name="gdesc">
			<column name="gdesc"></column>
		</property>
	</class>
</hibernate-mapping>

       测试类代码:

package com.demo.test;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import com.demo.entity.Grade;
import com.demo.entity.Student;
import com.demo.util.HibernateUtil;

/**
 * 单向多对一(学生--->班级)
 * @author Administrator
 * @date 2016年12月8日
 */
public class TestMany2One {
	
	//将学生添加到班级
	@Test
	public void testSave1(){
		Session session = HibernateUtil.getSession();
		Transaction  transaction= session.beginTransaction();
		
		Grade g=new Grade("Java一班","Java软件开发一班");
		
		Student stu1=new Student("张三", "男");
		Student stu2=new Student("李四", "男");
		
		//设置关联关系(单向多对一)
		stu1.setGrade(g);
		stu2.setGrade(g);
		
		session.save(stu1);
		session.save(stu2);
		
		//在清理缓存是发生错误TransientObjectException
		//因为Group为Transient状态,没有被session,在数据库中没有匹配的数据
		//而User为Persistent状态,在清理缓存时hibernate在缓存中无法找到Group对象
		//结论:Persistent状态的对象不能引用Transient状态的对象
		
		transaction.commit();
		HibernateUtil.closeSession(session);
	}
	
	//将学生添加到班级
		@Test
		public void testSave2(){
			Session session = HibernateUtil.getSession();
			Transaction  transaction= session.beginTransaction();
			
			Grade g=new Grade("Java一班","Java软件开发一班");
			session.save(g);
			
			Student stu1=new Student("张三", "男");
			Student stu2=new Student("李四", "男");
			
			//设置关联关系(单向多对一)
			stu1.setGrade(g);
			stu2.setGrade(g);
			
			session.save(stu1);
			session.save(stu2);
			
			//可以正确的保存数据
			//因为Group和User都是Persistent状态的对象
			//所以在hibernate清理缓存时在session中可以找到关联对象
			
			transaction.commit();
			HibernateUtil.closeSession(session);
		}
		
		//将学生添加到班级
		@Test
		public void testSave3(){
			Session session = HibernateUtil.getSession();
			Transaction  transaction= session.beginTransaction();
			
			Grade g=new Grade("Java一班","Java软件开发一班");
			
			Student stu1=new Student("张三", "男");
			Student stu2=new Student("李四", "男");
			
			//设置关联关系(单向多对一)
			stu1.setGrade(g);
			stu2.setGrade(g);
			
			session.save(stu1);
			session.save(stu2);
			
			//没有抛出TransientObjectException异常
			//因为使用了级联特性
			//hibernate会首先保存User的关联对象对象Group
			//Group和User就都是Persistent状态的对象了
			
			transaction.commit();
			HibernateUtil.closeSession(session);
		}
		
		//通过学生查询到班级名称
		@Test
		public void testLoad(){
			Session session = HibernateUtil.getSession();
			Transaction  transaction= session.beginTransaction();
			
			Student stu = (Student)session.load(Student.class, 1);
			System.out.println("stu.sname=" + stu.getSname());
			System.out.println("stu.grade.gname=" + stu.getGrade().getGname());
			
			transaction.commit();
			HibernateUtil.closeSession(session);
		}
		
}

       testSave1()方法

       Junit测试不成功:

       

       testSave2()方法

       控制台输出:

       

       数据库显示:

       

       在测试testSave3()方法之前需要在Student.hbm.xml中的<many-to-one>标签中加入cascade属性,我们删除

数据库中的两张表,重新生成表结构,并且重新插入原来想要插入的数据。

<!-- 配置单向多对一关联关系,设置cascade="all" -->
<many-to-one name="grade" class="com.demo.entity.Grade" column="gid" cascade="all"></many-to-one>

       testSave3()方法

       控制台输出:和testSave2()方法的控制台输出结果一致

       数据库显示:和testSave2()方法的数据库显示结果一致

       testLoad()方法

       控制台输出:

       

       单向多对一关联映射和关系数据库中的外键参照关系最匹配,即在多方的表中的一个外键参照另外一个表的主

键。通过在多方持有一方的引用实现,需要在多的一端使用<many-to-one>配置这是关键,还有就是注意级联属性

casacde。

       单向多对一关联映射维护的关系是:多指向一的关系,有了此关系,加载多的时候可以将一加载上来。

       


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值