【SSH三大框架】Hibernate基础第十二篇:load()懒加载分析以及一对一、一对多、多对一、多对多懒加载的分析
来源:互联网 发布:nsurlsessiond mac 编辑:程序博客网 时间:2024/05/17 23:22
一、懒加载的定义:
懒加载:在WEB应用程序中,经常会需要查询数据库,系统的响应速度在很大程度上是与数据库交互的响应。因此,如果能够优化与数据库的交互速度,则能够大大提高WEB应用的响应速度。
例如:当有一个Student类和一个Teacher类。当我们加载一个学生的所有信息,包括:学号,姓名等属性后,此时Student类中的Teacher类型的属性为null,当我们需要知道这个Student对应的Teacher属性的时候,我们才去加载这个Teacher对象。
如果,我们只需要知道学生信息,我们只需要查询一次数据库中的Stduent表,并且不需要根据外键查询Teacher表
如果,我们还需要知道老师信息,我们在查询Student表之后,还需要再做一次查询,查询Teacher表。
二、懒加载的原理及分析:
User.java
public class User { private int id; private String name; private Date birthday;//省略了setter和getter方法}User.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="cn.itcast.hibernate.domain"><class name="User" table="uuser" lazy="true"><id name="id"><generator class="native"/> </id><property name="name" /><property name="birthday" /></class></hibernate-mapping>这是User的实体类和映射文件。
我们来写一个测试的类:
public class Base {public static void main(String[] args) {User user = new User("lipenglong", new Date());addUser(user);User u = getUser(user.getId());System.out.println("Birthday:"+u.getBirthday());}static void addUser(User user) {Configuration cfg = new Configuration(); cfg.configure(); SessionFactory sf = cfg.buildSessionFactory(); Session s = sf.openSession(); Transaction tx = s.beginTransaction(); s.save(user); tx.commit(); s.close(); }static User getUser(int id){Session s = null;User u = null;try{s = HibernateUtil.getSession();u = (User) s.load(User.class,id);}finally{if(s!=null){s.close();}}return u;}}可以看到,我们首先是新增了一个user,然后要根据user的id在getUser(int id)方法中load了一个User对象,然后返回。
再在main函数中调用这个对象的birthday属性。
但是这样子会造成一个错误:
这是延迟加载的异常:在session对象打开的时候,我们延迟加载了一个对象,然后我们把session关闭了。在main函数中想使用这个对象,就会报出这个异常。
有一下的几种解决方法:
1、换成get(class,id)方法
换成get(class,id)方法之后,我们会在getUser(int id)函数执行的时候,就会生成一条sql语句:
2、在load(class,id)方法之后,也就是session关闭之前,初始化这个对象(增加:Hibernate.initialize(u);语句)。
在增加这条语句之后,我们就可以在main函数中调用这个对象的方法了:
我们可以把Birthday属性打印出来了。
3、在load(class,id)方法之后,也就是session关闭之前,调用这个对象的方法,就相当于初始化了(增加:u.getName();语句或者u.getBirthday();)
static User getUser(int id){Session s = null;User u = null;try{s = HibernateUtil.getSession();u = (User) s.load(User.class,id);u.getName();//u.getBirthday();}finally{if(s!=null){s.close();}}return u;}我们修改之后,就可以在main函数中调用这个对象的方法了。
三、一对一懒加载的原理及分析:
在一对一的时候,查询主对象时默认不是懒加载。即:查询主对象的时候也会把从对象查询出来。
需要把主对象配制成lazy="true" constrained="true" fetch="select"。此时查询主对象的时候就不会查询从对象,从而实现懒加载。
一对一的时候,查询从对象默认是懒加载。即:查询从对象的时候不会把主对象查询出来。而是查询出来的是主对象的代理对象。
下边,我们用Person和IdCard举例子:
Person.java:
public class Person {private int id;private String name;private IdCard idCard;public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public IdCard getIdCard() {return idCard;}public void setIdCard(IdCard idCard) {this.idCard = idCard;}}Person.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="cn.itcast.hibernate.domain"><class name="Person" table="person"><id name="id"><generator class="native"/> </id><property name="name" /><one-to-one name="idCard"/></class></hibernate-mapping>IdCard.java:
public class IdCard {private int id;private Date userfulLift;private Person person;public int getId() {return id;}public void setId(int id) {this.id = id;}public Date getUserfulLift() {return userfulLift;}public void setUserfulLift(Date userfulLift) {this.userfulLift = userfulLift;}public Person getPerson() {return person;}public void setPerson(Person person) {this.person = person;}}
IdCard.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="cn.itcast.hibernate.domain"><class name="IdCard" table="id_card" ><id name="id"><generator class="foreign"><param name="property">person</param></generator> </id><property name="userfulLift" column="useful_life" /><one-to-one name="person" constrained="true"/></class></hibernate-mapping>
然后,我们写一个测试类:
package cn.itcast.hibernate;import java.util.Date;import org.hibernate.Hibernate;import org.hibernate.Session;import org.hibernate.Transaction;import cn.itcast.hibernate.domain.IdCard;import cn.itcast.hibernate.domain.Person;public class One2One {public static void main(String[] args) {add();System.out.println("——————————————————");IdCard idCard = queryIdCard(1);System.out.println("————————————————————");Person p = queryPerson(1);}static Person add(){Session s = null;Transaction tx = null;try{s = HibernateUtil.getSession();IdCard idCard = new IdCard();idCard.setUserfulLift(new Date());Person p = new Person();p.setName("p1");p.setIdCard(idCard);idCard.setPerson(p);tx =s.beginTransaction();s.save(p);s.save(idCard);tx.commit();return p;}finally{if(s!=null){s.close();}}}static IdCard queryIdCard(int id){Session s = null;Transaction tx = null;try{s = HibernateUtil.getSession();tx = s.beginTransaction();IdCard idCard = (IdCard) s.get(IdCard.class, id);tx.commit();return idCard;}finally{if(s!=null){s.close();}}}static Person queryPerson(int id){Session s = null;Transaction tx = null;try{s = HibernateUtil.getSession();tx = s.beginTransaction();Person p = (Person) s.get(Person.class, id);tx.commit();return p;}finally{if(s!=null){s.close();}}}}我们在main函数中,调用了两个方法,分别是查询从对象IdCard和查询主对象Person,我们可以看下控制台打印出来的sql语句:
可以看到,我们生成了两条insert语句和两条查询语句。第一条查询语句仅仅是查询从表id_card表,但是第二条查询语句会根据采用连接的方式先查询主表Person再查询从表id_card。
所以,在一对一的关联中,Hibernate默认从表有懒加载,但是主表没有。
四、多对一关联的懒加载:
多对一的时候,查询主对象时默认是懒加载。即:查询主对象的时候不会把从对象查询出来。
多对一的时候,查询从对象时默认是懒加载。即:查询从对象的时候不会把主对象查询出来。
五、多对多关联的懒加载:
同上所述,总是会出现懒加载的现象。
懒加载在Hibernate中很多地方是默认的,那么我们如何关闭懒加载呢?
请看下一篇:
【SSH三大框架】Hibernate基础第十三篇:lazy、constrained、fetch三个属性的作用和使用方法
- 【SSH三大框架】Hibernate基础第十二篇:load()懒加载分析以及一对一、一对多、多对一、多对多懒加载的分析
- 【SSH三大框架】Hibernate基础第六篇:多对一关联关系的映射、分析及添加、查询
- Hibernate一对一,一对多懒加载的要求
- Hibernate一对一,一对多懒加载的要求
- Mybatis的一对多,多对一以及延迟加载
- Mybatis的一对多,多对一以及延迟加载
- Java 框架之Hibernate (三、Hibernate一对多及多对多的关系分析)
- 【SSH三大框架】Hibernate基础第八篇:多对多关联关系的操作
- 【SSH三大框架】Hibernate基础第七篇:一对多关联关系的操作
- 数据库关系 一对多/多对一/一对一/多对多 关系分析
- Hibernate关联关系映射 一对一 一对多 多对一
- Hibernate一对一,一对多,多对多
- hibernate多对一、一对一、一对多、多对多的配置方法
- hibernate中多对一、一对一、一对多、多对多的配置方法
- hibernate中多对一、一对一、一对多、多对多的配置方法
- 数据库建表的各徙关系-- 一对多/多对一/一对一/多对多 关系分析
- 数据库建表的各徙关系-- 一对多/多对一/一对一/多对多 关系分析
- 数据库建表的各徙关系-- 一对多/多对一/一对一/多对多 关系分析
- javascript B,KB,MB等单位换算
- 国内外大型SNS网站后台架构对比
- 宣布 Azure Backup 支持备份 Windows Server 2008
- 大型网站的负载均衡器、db proxy和db
- Bootstrap学习笔记
- 【SSH三大框架】Hibernate基础第十二篇:load()懒加载分析以及一对一、一对多、多对一、多对多懒加载的分析
- Java 1.6 新特性
- oracle 存储过程详细介绍(创建,删除存储过程,参数传递等)
- the nuclear norm
- SQL语句中Exists
- 第十四周项目一:二维数组折腾(一)
- 单链表之C实现
- 牵手阿里,魅族能否成就“更大格局”?
- 使用COS组件实现文件上传