Hibernate(四)单向多对一映射下的增删改查

Hibernate单向多对一映射下的增删改查


注:作为初学者,本文仅为了巩固自己学习的知识亦或帮助初学者,如有缺漏,请见谅

在软件开发中,类与类之间最普遍的关系就是关联关系,而且关联关系是有方向的。以Student类和Grade类为例,一个年级包含多个学生,一个学生只对应一个年级,从Student到Grade就是多对一映射,从Grade到Student到Student就是一对多映射,同时包含两种关联关系就是双向多对一关系。本文仅介绍单向多对一映射关系。

一、配置单向多对一映射关系
以Student和Grade的关联关系为例,那么该如何来配置呢?既然一个Student只属于一个Grade,所以在Student持久类中应该定义一个Grade的对象;然后在映射文件中配置,下面详细介绍

1. 首先在Student类中定义一个Grade类的对象
public class Student implements Serializable{
	private int id;
	private int age;
	private String name;
	private Grade grade;
	//...
}
2. 配置映射文件
<hibernate-mapping package="com.wzj.entity">
	<class name="Student" table="Student">
		<id name="id" type="java.lang.Integer" column="id">
			<generator class="assigned"></generator>
		</id>
		<property name="name" type="java.lang.String" column="name"></property>
		<property name="age" type="java.lang.Integer" column="age"></property>
		<!-- 此句是关键 -->
		<many-to-one name="grade" class="Grade" column="gradeid"></many-to-one>
	</class>
	<!--省去Grade映射-->
</hibernate-mapping>
二、单向多对一关系的使用
1.
我们首先创建两个Student对象,1个Grade对象,并建立关系,那么我们该以什么样的顺序来保存呢?
public static void main(String[] args) {
		Session session=HibernateUtil.currentSession();
		Transaction tx=session.beginTransaction();
		
		testCreate(session);
		
		tx.commit();
		HibernateUtil.closeSession();
		
	}
	public static void testCreate(Session session){
		Student s1=new Student(1,20,"student-1");
		Student s2=new Student(2,20,"student-2");
		Grade g=new Grade(1,"一年级");
		s1.setGrade(g);
		s2.setGrade(g);
		
		//先保存“1”的一方,再保存“n”的一方
		session.save(g);
		session.save(s1);
		session.save(s2);
	}
然后运行,数据库中成功更新,控制台输出了3条insert语句,一条插入Grade,2条插入Student。再来看,先保存n的一方:

public static void testCreate(Session session){
		Student s1=new Student(3,20,"student-3");
		Student s2=new Student(4,20,"student-4");
		Grade g=new Grade(2,"二年级");
		s1.setGrade(g);
		s2.setGrade(g);
		
		//先保存“n”的一方,再保存“1”的一方
		session.save(s1);
		session.save(s2);
		session.save(g);
	}
然后运行,数据库成功更新,不过这次控制台输出了6条sql语句,第一条是查询年级是否存在,第2、3、4条是插入学生和年级,最后两条是更新学生的GradeId

小结:当我们先插入Student的时候,还要对应插入Grade的ID,此时数据库中并不存在这个Id,所以,Hibernate会先为我们插入一个空值(当然,数据库中的GradeId得允许为空),然后插入Grade之后再根据此时生成的GradeId去更新学生的信息;由此可见,这种方式增加了对数据库的访问频率,降低了程序的性能,所以推荐大家尽量少使用这种方式。

2.查
如下代码:
public static void testQuery(Session session){
		Student s=(Student)session.get(Student.class, 1);
		System.out.println(s.getName());
	}
运行发现只是发送了一条sql语句,与之关联的Grade对象并没有查询;假如再加上一句:
Grade g=s.getGrade();
		System.out.println(g.getGradeName());
此时再次运行就会发现变成了两条sql语句。倘若我们这样:
public static void testQuery(Session session){
		Student s=(Student)session.get(Student.class, 1);
		System.out.println(s.getName());
		session.close();
		Grade g=s.getGrade();
		System.out.println(g.getGradeId());
		System.out.println(g.getGradeName());
	}
然后会发现,程序在执行g.getGradeName()的时候抛出了一个叫做LazyInitializationException的异常(为什么可以获取到Grade.GradeId呢?)其实这个异常就是Hibernate中常见的懒加载机制异常。


小结:当我们查询“n”的一方时,默认情况下只会查询到n的一方的对象,而与之关联的对象并不会查询,这就是Hibernate中的懒加载(延迟加载)机制。当我们需要使用到关联对象的属性的时候,Hibernate才会发送对应的sql语句去查询并实例化Grade,在实例化之前Grade只是一个代理对象,仅仅拥有一个和Student关联的属性值(GradeId),而其他属性统统无值,关于懒加载的详解,这里有一篇不错的 文章,大家可以参考一下:http://blog.csdn.net/sanjy523892105/article/details/7071139

3.改、删
对于这两种情况来说,使用起来就比较简单了,没有什么特别之处。
需要注意的是:执行删除时,在不设定级联的情况下,并且“1”的一方有“n”的一方在引用的时候,不能直接删除“1”这一方的对象。








  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值