`

Hibernate延迟加载案例 (多: 一: 一,附代码)

阅读更多
摘自圣思园Hibernate20.一对一关联及左外连接深度解析  25分钟。


场景:
有三个对象类, Student, IdCard, Team.
Student和IdCard是一对一关系。
而Team和Student是一对多关系。


Student和IdCard的类声明以及映射文件配置和http://alleni123.iteye.com/admin/blogs/1978000这里的类大致一样。  只是Student里面多了一个 private Team team,
以及配置文件里面要加入一个<many-to-one>映射到Team对象。

Team类如下:
public class Team
{
	private String id;
	private String name;
	
	private Set<Student> students;
}

Team配置文件:
	<class name="Team" table="test_team">
		<id name="id" column="id" type="string">
			<generator class="uuid"></generator>
		</id>
		 
		 <property name="name" column="name" type="string"/>
		 	
		 <!-- 在一对多的对应关系中,都是让多的一方来维持对应关系,所以在这里设置为true,既由students来维持关系-->
		 <set name="students" [b]lazy="false"[/b] cascade="all" inverse="true">
		 	<key column="team_id"/>
		 	<one-to-many class="Student"/>
		 </set>
		 
		 
	</class>


插入代码:

public class HibernateTeam_1insert
{
	public static void main(String[] args)
	{
		Session session=HibernateUtil.openSession();
		
		Team team=new Team(null,"impl_team",null);
		
		 
		
		
		Student s1=new Student("alleni", null);
		Student s2=new Student("eline",null);
		
		IdCard card1=new IdCard(001, s1);
		
		IdCard card2=new IdCard(002,s2);
		
	 	s1.setIdCard(card1); 
	 	s2.setIdCard(card2);
	 	//如果没这两行,便会报错[url]http://alleni123.iteye.com/admin/blogs/1978483[/url]
	 	
	 	s1.setTeam(team);
	 	s2.setTeam(team);
	 	//如果没有这两行,student对象将不会和team在数据库中关联,并且不会报错。   为了解决这个问题, 可以在Student映射配置文件中配置not-null=true,如此Hibernate便会让Nullability类执行checkNullability().
	 	
		
		
		team.setStudents(ArraysHelper.asSet(s1,s2));
		
		
		Transaction tx=session.beginTransaction();
		
		session.save(team);
		
		tx.commit();
		
		
		
		
	}
}	


代码运行后的数据库如下:






=================================================
查询
延迟加载查询


查询代码如下:
	Session session=HibernateUtil.openSession();
		
	 
	Team team = (Team) session.load(Team.class,"4028bd814279be81014279be84ff0000" );
  System.out.println(team.getName());



Hibernate: select team0_.id as id1_5_0_, team0_.name as name2_5_0_ from test_team team0_ where team0_.id=?
Hibernate: select students0_.team_id as team3_5_2_, students0_.id as id1_4_2_, students0_.id as id1_4_1_, students0_.name as name2_4_1_, students0_.team_id as team3_4_1_, idcard1_.id as id1_1_0_, idcard1_.card_number as card2_1_0_ from test_student students0_ inner join test_idcard idcard1_ on students0_.id=idcard1_.id where students0_.team_id=?


这里Hibernate发出了两条查询语句,第二条我们可以看到很多对象名称,包括student,idcard。
也就是说Hibernate使用了一个inner join查询将所有关联的对象都提取了出来。


之所以会这样, 是因为上面在Team.xml配置文件中,<set>元素的lazy被设置成了false,延迟加载被禁用。
因此即使我们只需要查询team的名字,Hibernate也会使用join方法的SQL来获取所有关联对象的内容。
要解决这个问题, 只要设置Team.xml中的<set>的lazy=true,便能解决。
 //Team.xml
 //<set name="students" lazy="true" cascade="all" inverse="true"  fetch="select">
	Team team = (Team) session.load(Team.class,"4028bd814279be81014279be84ff0000" );
	 	
		   System.out.println(team.getName());

//执行结果
//Hibernate: select team0_.id as id1_5_0_, team0_.name as name2_5_0_ from test_team team0_ where team0_.id=?
//impl_team


这里要注意设置fetch="select",(其实默认就是select)
如果fetch=join,那么即使lazy=true,也还是会通过inner join来进行关联加载。即使这里指查询了team的名称,也会发出一长串join连接的sql语句来查到其它内容。

小知识点:
在Hibernate.cfg.xml中配置property max_fetch_depth的值,可以限制Hibernate在查询时的级联深度, 此方法可以防止Hibernate进行无限止的级联查询,耗费数据库资源。
<property name="hibernate.max_fetch_depth">1</property>
1表示最多进行一级的查询。


这里遇到了一个问题,就是在设置Student和IdCard的延迟加载时,Hibernate没有实现延迟加载。


===============
最后把至今为止hibernate测试的代码传一下。
  • 大小: 87.4 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics