【Hibernate】lazy延迟加载
2017-02-09 11:15
267 查看
延迟加载(lazy load)是(也称为懒加载)Hibernate3关联关系对象默认的加载方式,延迟加载机制是为了避免一些无谓的性能开销而提出来的,所谓延迟加载就是当在真正需要数据的时候,才真正执行数据加载操作。可以简单理解为,只有在使用的时候,才会发出sql语句进行查询。
hibernate的lazy策略可以使用在如下四个场景:
* <class>标签上,可以取值:“true/false”
* <property>标签上,可以取值:“true/false”,但是需要类增强工具配合使用,不常用。
* <set>/<list>标签上,可以取值:“true/false/extra”,对集合的延迟加载很常用。
* <many-to-one>/<one-to-one>单端关联标签上,可以取值"false/proxy/noproxy"
最常使用的地方就是在<set>/<list>集合上。
一个Demo
public void testQuery1(){
Session session = null;
try{
session = HibernateUtils.getSession();
session.beginTransaction();
//查询操作,不会发出sql
User user = (User)session.load(User.class, 1);
//显示id--(代理操作)
System.out.println("user.id=" + user.getId());
//显示name -- (数据库开始查询操作)
System.out.println("user.name=" + user.getName());
System.out.println("user.password=" + user.getPassword());
session.getTransaction().commit();
}catch(Exception e){
e.printStackTrace();
}finally{
HibernateUtils.closeSession(session);
}
} 这个例子中:
(1)因为load默认支持lazy加载,执行session.load之后,打印user.getId();因为传入的id,且通过代理操作,并未进行数据库查询,在打印user.getName()时,开始进行查询操作。
(2)如果Name属性支持lazy(在hbm.xml中将该属性设置为lazy加载),执行到"user.getName()"的时候,才会把Name值加载出来。
现在修改这个Demo:
public void testQuery2(){
Session session = null;
User user = null;
try{
session = HibernateUtils.getSession();
session.beginTransaction();
user = (User)session.load(User.class, 1);
session.getTransaction().commit();
}catch(Exception e){
e.printStackTrace();
}finally{
HibernateUtils.closeSession(session);
//放在session关闭之后
System.out.println("user.name=" + user.getName());
}
}
将user.getName()方法写到了closeSession之后,报出SessionException的错误,可见,hibernate中使用lazy策略,必须放到session当中。
对Collection集合中的“lazy”策略
通过一个Load的Demo
public void testLoad1(){
Session session = null;
try{
session = HibernateUtils.getSession();
session.beginTransaction();
//(1)
Classes classes = (Classes)session.load(Classes.class, 1);
//(2)
System.out.println("Classes.name=" + classes.getName());
//(3)
Set students = classes.getStudents();
//(4)
for(Iterator iter=students.iterator(); iter.hasNext();){
Student student = (Student)iter.next();
System.out.println("student.name=" + student.getName());
}
session.getTransaction().commit();
}catch(Exception e){
e.printStackTrace();
session.getTransaction().rollback();
}finally{
HibernateUtils.closeSession(session);
}
} 如上,代码中标记了(1)(2)(3)(4)共计4条测试语句,默认的hbm.xml配置中,对<set>的lazy形式也是“true”,当调用testLoad1()的时候,
不会发出sql的有:(1)(3)
会发出Sql的有:(2)(4)
做到了,真正的 只有在使用的时候,才会加载,即体现出lazy加载的一个好处。
然而对于lazy="true"有一个影响效率性能的地方,参考这个demo:
public void testLoad2(){
Session session = null;
try{
session = HibernateUtils.getSession();
session.beginTransaction();
//不会发出sql
Classes classes = (Classes)session.load(Classes.class, 1);
//会发出sql
System.out.println("Classes.name=" + classes.getName());
//不会发出sql
Set students = classes.getStudents();
//会发出查询该班级全部学生的sql语句,存在效率问题
System.out.println("count=" + students.size());
session.getTransaction().commit();
}catch(Exception e){
e.printStackTrace();
session.getTransaction().rollback();
}finally{
HibernateUtils.closeSession(session);
}
}
将for循环替换为查询students.size();使用lazy="true"策略,加载过程中,对size的查询虽然支持lazy,但是发出的sql语句是select * from t_table,改善如下:
将lazy="true"修改为lazy="extra",此时发出的sql语句为"select count(*) from t_table",提升了效率,同时extra继承了true的所有优点,对<set>最好使用lazy="extra",当然使用lazy="false",肯定就不支持集合的延迟加载了。
附注:<class>上的lazy策略,影响的仅仅是<property>这类普通属性,对于<set>/<list>没有影响。
hibernate的lazy策略可以使用在如下四个场景:
* <class>标签上,可以取值:“true/false”
* <property>标签上,可以取值:“true/false”,但是需要类增强工具配合使用,不常用。
* <set>/<list>标签上,可以取值:“true/false/extra”,对集合的延迟加载很常用。
* <many-to-one>/<one-to-one>单端关联标签上,可以取值"false/proxy/noproxy"
最常使用的地方就是在<set>/<list>集合上。
一个Demo
public void testQuery1(){
Session session = null;
try{
session = HibernateUtils.getSession();
session.beginTransaction();
//查询操作,不会发出sql
User user = (User)session.load(User.class, 1);
//显示id--(代理操作)
System.out.println("user.id=" + user.getId());
//显示name -- (数据库开始查询操作)
System.out.println("user.name=" + user.getName());
System.out.println("user.password=" + user.getPassword());
session.getTransaction().commit();
}catch(Exception e){
e.printStackTrace();
}finally{
HibernateUtils.closeSession(session);
}
} 这个例子中:
(1)因为load默认支持lazy加载,执行session.load之后,打印user.getId();因为传入的id,且通过代理操作,并未进行数据库查询,在打印user.getName()时,开始进行查询操作。
(2)如果Name属性支持lazy(在hbm.xml中将该属性设置为lazy加载),执行到"user.getName()"的时候,才会把Name值加载出来。
现在修改这个Demo:
public void testQuery2(){
Session session = null;
User user = null;
try{
session = HibernateUtils.getSession();
session.beginTransaction();
user = (User)session.load(User.class, 1);
session.getTransaction().commit();
}catch(Exception e){
e.printStackTrace();
}finally{
HibernateUtils.closeSession(session);
//放在session关闭之后
System.out.println("user.name=" + user.getName());
}
}
将user.getName()方法写到了closeSession之后,报出SessionException的错误,可见,hibernate中使用lazy策略,必须放到session当中。
对Collection集合中的“lazy”策略
通过一个Load的Demo
public void testLoad1(){
Session session = null;
try{
session = HibernateUtils.getSession();
session.beginTransaction();
//(1)
Classes classes = (Classes)session.load(Classes.class, 1);
//(2)
System.out.println("Classes.name=" + classes.getName());
//(3)
Set students = classes.getStudents();
//(4)
for(Iterator iter=students.iterator(); iter.hasNext();){
Student student = (Student)iter.next();
System.out.println("student.name=" + student.getName());
}
session.getTransaction().commit();
}catch(Exception e){
e.printStackTrace();
session.getTransaction().rollback();
}finally{
HibernateUtils.closeSession(session);
}
} 如上,代码中标记了(1)(2)(3)(4)共计4条测试语句,默认的hbm.xml配置中,对<set>的lazy形式也是“true”,当调用testLoad1()的时候,
不会发出sql的有:(1)(3)
会发出Sql的有:(2)(4)
做到了,真正的 只有在使用的时候,才会加载,即体现出lazy加载的一个好处。
然而对于lazy="true"有一个影响效率性能的地方,参考这个demo:
public void testLoad2(){
Session session = null;
try{
session = HibernateUtils.getSession();
session.beginTransaction();
//不会发出sql
Classes classes = (Classes)session.load(Classes.class, 1);
//会发出sql
System.out.println("Classes.name=" + classes.getName());
//不会发出sql
Set students = classes.getStudents();
//会发出查询该班级全部学生的sql语句,存在效率问题
System.out.println("count=" + students.size());
session.getTransaction().commit();
}catch(Exception e){
e.printStackTrace();
session.getTransaction().rollback();
}finally{
HibernateUtils.closeSession(session);
}
}
将for循环替换为查询students.size();使用lazy="true"策略,加载过程中,对size的查询虽然支持lazy,但是发出的sql语句是select * from t_table,改善如下:
将lazy="true"修改为lazy="extra",此时发出的sql语句为"select count(*) from t_table",提升了效率,同时extra继承了true的所有优点,对<set>最好使用lazy="extra",当然使用lazy="false",肯定就不支持集合的延迟加载了。
附注:<class>上的lazy策略,影响的仅仅是<property>这类普通属性,对于<set>/<list>没有影响。
相关文章推荐
- 关于延迟加载(lazy)和强制加载(Hibernate.initialize(Object proxy) )
- Hibernate的延迟加载 ,懒加载,lazy
- Hibernate使用LAZY延迟加载,initialize获取延迟加载关联内容
- hibernate 延迟加载(Lazy)问题spring下解决方法
- 关于延迟加载(lazy)和强制加载(Hibernate.initialize(Object proxy) )
- 延迟加载 ERROR org.hibernate.LazyInitializationException:42 - could not initialize proxy - ...
- hibernate延迟加载的传说级错误org.hibernate.LazyInitializationException: could not initialize proxy - no Session
- 关于延迟加载(lazy)和强制加载(Hibernate.initialize(Object proxy) )
- Hibernate 延迟加载,lazy属性配置。以及org.hibernate.LazyInitializationException
- 关于延迟加载(lazy)和强制加载(Hibernate.initialize(Object proxy) )
- Hibernate之lazy延迟加载
- Hibernate学习24 -- 延迟加载1 -- 类对象Lazy特征
- Hibernate学习25 -- 延迟加载2 -- 集合Lazy特征
- 关于延迟加载(lazy)和强制加载(Hibernate.initialize(Object proxy) )
- 关于延迟加载(lazy)和强制加载(Hibernate.initialize(Object proxy) )
- Hibernate学习26 -- 延迟加载3 -- 关联lazy特征
- [转]PO和VO、关于延迟加载(lazy)和强制加载(Hibernate.initialize(Object proxy) )
- Hibernate: 关于延迟加载(lazy)和强制加载 : Hibernate.initialize()
- org.hibernate.LazyInitializationException【延迟加载异常】
- Hibernate中Lazy延迟加载