初识懒加载:懒加载是指程序推迟访问数据库,这样做可以保证有时候不必要的访问数据库,因为访问一次数据库是比较耗时的。
1) Load()方法的懒加载:如果在session关闭之前都没有对数据库进行访问或进行对所load的对象进行初始化即:Hibernate. initialize(employeeSet) ,则肯定会报错。因为在为访问数据库之前load()方法懒加载返回的是一个对象的代理,获取它的属性都是获取不到的。但是,如果在session关闭之前访问了数据库或对load的对象进行了初始化,则会强行访问一次数据库进行查询并将真正的对象赋值给代理.
2) on e-to-on e(元素)懒加载:
此种元素的懒加载使用比较少,因为它对性能的增加表现不明显,因此Hibernate对查询主对象的”一对一”懒加载默认是关闭的。
只有基于外键关联方式的“一对一”才能用懒加载。
实现此种懒加载必须在从对象这边同时满足三个条件:
① lazy!=false(lazy的属性有三个选项分别为:no-proxy、false和proxy;
② Constrained = true ;
③ fetch=select。
注意:
1. 主表不能有constrained=true,所以主表没有懒加载。
2. 不在session关闭之前查询IdCard的属性会报错,但getId()和getClass()除外。
3. 在Person和IdCard“一对一”关联关系中通过知道IdCard的id查对应的IdCard时候,Hibernate只会查IdCard相关的信息(不包括IdCard中person信息),只有在代码中执行像cardId.getPerson()这样访问IdCard里面的属性时候才会查询数据库查其中person相关信息。
4. 因为仅仅是“一对一”关联,即使不用懒加载只不过仅仅多查了一条数据而已,所以性能上看不出有什么大的提高。
举例:
Person的映射文件保持不变:
<hibernate-mapping package="cn.itcast.domain">
<class name="Person">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<on
e-to-on
e name="idCard"/>
</class>
</hibernate-mapping>
修改IdCard映射文件:
<hibernate-mapping package="cn.itcast.domain">
<class name="IdCard" table="id_card">
<id name="id">
<generator class="foreign">
<param name="property">person</param>
</generator>
</id>
<property name="usefulLife" column="userful_life"/>
<on e-to-on
e name="person" constrained="true" lazy="proxy" fetch="select"/>
</class>
</hibernate-mapping>
注意:
1. lazy=”proxy”和fetch=”select”在这里是可以不用写明的,因为Hibernate默认lazy=”proxy” fetch=”select”.
2. lazy的选项proxy表示什么时候加载信息,即:通过代理方式需要加载时候才加载而不是不管需不需要全都加载);fetch的选项select表示通过select方式查询需要的信息,选项join表示通过执行内连接把所有信息统统查出来。
3) On e-to-many(元素)懒加载:
这种关联关系执行懒加载对程序执行效率是非常有效的。如果不使用懒加载,在论坛中仅仅想查询某贴主时候,则将会一次性将回帖全部查询出来,这不仅浪费时间也是不必要的查询,所以这里使用懒加载时候需要时候才查这是正确的方案。
Hibernate默认对on e-to-many就是使用的懒加载,但用户也可以取消懒加载操作:
方法一:设置lazy=”false”;
方法二:设置fetch=”join”.
4) Many-to-on e(元素)懒加载:
此关联关系的懒加载和on e-to-on
e的懒加载一样都是可要可不要的,因为对执行效率的提高都不是非常明显。
5) Many-to-many(元素)懒加载:
此关联关系的懒加载和on e-to-many的懒加载一样对程序的执行效率的提高都是非常明显的。
6) Hibernate默认都是使用懒加载的,如果定义的查询方法 :
static Employee query(int id)中没有对Employee employee =( Employee)session. get(Employee. class, id);中的代理对象idCard没有进行初始化,而在调用此方法时候使用了如下查询操作:
Employee employee =query(1);
System.out.println(employee. getDept(). getName());
这样肯定会出错,因为session关闭前没有初始化Employee,难道要在static Employee query(int id)中加上Hibernate. initialize(employee)进行代理初始化?
我们知道如果不使用懒加载而在程序中不查employee中的Department对象属性,这样会很浪费资源的。
(1) 解决方法一:修改query()方法为:
static Employee query(int id, boolean deptIncluded)
{
Session session=null;
Session=HibernateUtil.getSession();
Employee employee=(Employee)session.get(Employee.class, id);
If(deptIncluded)
Hibernate. initialize(employee);
Return employee;
}
以后调用query()方法是多加一个参数用来指定是否需要初始化代理对象。
(2) 解决方法二:使用OpenSessionInView:
imp ort java.io.IOException;
imp ort javax.servlet.Filter;
imp ort javax.servlet.FilterChain;
imp ort javax.servlet.FilterConfig;
imp ort javax.servlet.ServletException;
imp ort javax.servlet.ServletRequest;
imp ort javax.servlet.ServletResponse;
imp ort org.hibernate.HibernateException;
imp ort cn.itcast.util.HibernateUtil;
public class HibernateSessionUtilFilter implements Filter
{
protected FilterConfig filterConfig=null;
public HibernateSessionUtilFilter()
{
}
@Override
public void destroy()
{
this.filterConfig=null;
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException
{
try
{
chain.doFilter(request, response);
}
finally
{
try
{
HibernateUtil.commitTransaction();
}
catch(HibernateException he)
{
HibernateUtil.rollbackTransaction();
}
finally
{
System.out.println("closeSession已经被执行");
HibernateUtil.closeSession();
}
}
}
@Override
public void init(FilterConfig filterConfig) throws ServletException
{
this.filterConfig=filterConfig;
}
}
最后不要忘记在配置文件中配置此filter。
注意:尽管“Open Session In View”能够解决Hibernate框架的延迟初始化中的Session关闭问题,但也有副作用:如果用户的请求的流程中某一步被阻塞,那在这期间的Session就一直被占用而不能被释放掉。这也导致本次事务访问的事务比较长,这与“对数据库表中的数据访问的事务尽可能短小”的原则相抵触。
1) Load()方法的懒加载:如果在session关闭之前都没有对数据库进行访问或进行对所load的对象进行初始化即:Hibernate. initialize(employeeSet) ,则肯定会报错。因为在为访问数据库之前load()方法懒加载返回的是一个对象的代理,获取它的属性都是获取不到的。但是,如果在session关闭之前访问了数据库或对load的对象进行了初始化,则会强行访问一次数据库进行查询并将真正的对象赋值给代理.
2) on
此种元素的懒加载使用比较少,因为它对性能的增加表现不明显,因此Hibernate对查询主对象的”一对一”懒加载默认是关闭的。
只有基于外键关联方式的“一对一”才能用懒加载。
实现此种懒加载必须在从对象这边同时满足三个条件:
① lazy!=false(lazy的属性有三个选项分别为:no-proxy、false和proxy;
② Constrained = true ;
③ fetch=select。
注意:
1. 主表不能有constrained=true,所以主表没有懒加载。
2. 不在session关闭之前查询IdCard的属性会报错,但getId()和getClass()除外。
3. 在Person和IdCard“一对一”关联关系中通过知道IdCard的id查对应的IdCard时候,Hibernate只会查IdCard相关的信息(不包括IdCard中person信息),只有在代码中执行像cardId.getPerson()这样访问IdCard里面的属性时候才会查询数据库查其中person相关信息。
4. 因为仅仅是“一对一”关联,即使不用懒加载只不过仅仅多查了一条数据而已,所以性能上看不出有什么大的提高。
举例:
Person的映射文件保持不变:
<hibernate-mapping package="cn.itcast.domain">
<class name="Person">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<on
</class>
</hibernate-mapping>
修改IdCard映射文件:
<hibernate-mapping package="cn.itcast.domain">
<class name="IdCard" table="id_card">
<id name="id">
<generator class="foreign">
<param name="property">person</param>
</generator>
</id>
<property name="usefulLife" column="userful_life"/>
<on
</class>
</hibernate-mapping>
注意:
1. lazy=”proxy”和fetch=”select”在这里是可以不用写明的,因为Hibernate默认lazy=”proxy” fetch=”select”.
2. lazy的选项proxy表示什么时候加载信息,即:通过代理方式需要加载时候才加载而不是不管需不需要全都加载);fetch的选项select表示通过select方式查询需要的信息,选项join表示通过执行内连接把所有信息统统查出来。
3) On
这种关联关系执行懒加载对程序执行效率是非常有效的。如果不使用懒加载,在论坛中仅仅想查询某贴主时候,则将会一次性将回帖全部查询出来,这不仅浪费时间也是不必要的查询,所以这里使用懒加载时候需要时候才查这是正确的方案。
Hibernate默认对on
方法一:设置lazy=”false”;
方法二:设置fetch=”join”.
4) Many-to-on
此关联关系的懒加载和on
5) Many-to-many(元素)懒加载:
此关联关系的懒加载和on
6) Hibernate默认都是使用懒加载的,如果定义的查询方法 :
static Employee query(int id)中没有对Employee employee =( Employee)session. get(Employee. class, id);中的代理对象idCard没有进行初始化,而在调用此方法时候使用了如下查询操作:
Employee employee =query(1);
System.out.println(employee. getDept(). getName());
这样肯定会出错,因为session关闭前没有初始化Employee,难道要在static Employee query(int id)中加上Hibernate. initialize(employee)进行代理初始化?
我们知道如果不使用懒加载而在程序中不查employee中的Department对象属性,这样会很浪费资源的。
(1) 解决方法一:修改query()方法为:
static Employee query(int id, boolean deptIncluded)
{
Session session=null;
Session=HibernateUtil.getSession();
Employee employee=(Employee)session.get(Employee.class, id);
If(deptIncluded)
Hibernate. initialize(employee);
Return employee;
}
以后调用query()方法是多加一个参数用来指定是否需要初始化代理对象。
(2) 解决方法二:使用OpenSessionInView:
imp
imp
imp
imp
imp
imp
imp
imp
imp
public class HibernateSessionUtilFilter implements Filter
{
protected FilterConfig filterConfig=null;
public HibernateSessionUtilFilter()
{
}
@Override
public void destroy()
{
this.filterConfig=null;
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException
{
try
{
chain.doFilter(request, response);
}
finally
{
try
{
HibernateUtil.commitTransaction();
}
catch(HibernateException he)
{
HibernateUtil.rollbackTransaction();
}
finally
{
System.out.println("closeSession已经被执行");
HibernateUtil.closeSession();
}
}
}
@Override
public void init(FilterConfig filterConfig) throws ServletException
{
this.filterConfig=filterConfig;
}
}
最后不要忘记在配置文件中配置此filter。
注意:尽管“Open Session In View”能够解决Hibernate框架的延迟初始化中的Session关闭问题,但也有副作用:如果用户的请求的流程中某一步被阻塞,那在这期间的Session就一直被占用而不能被释放掉。这也导致本次事务访问的事务比较长,这与“对数据库表中的数据访问的事务尽可能短小”的原则相抵触。