1)懒加载定义:也就是在用到查询的对象的时候才会执行sql去数据库取数据,如果用不到那就不查了
2)懒加载作用:可能能够节省查询数据库操作
3)懒加载原理:也就是使用load方法获得的是类的代理,而不是类本身
4)使用条件:
1> 查询的类的lazy属性为true
2> 查询时候使用的是load方法
3> 查询的类不是final的(因为final就不能生成子类,所以就不能生成代理类)
5)实例
public class Employee {
private Long id;
private String name;
private Department department;
............
}
<class name="cn.com.cpf.pojo.Department" table="t_department" lazy="true">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="name"/>
<set name="employees" inverse="false">
<key column="departmentId"/>
<one-to-many class="cn.com.cpf.pojo.Employee" />
</set>
</class>
SessionFactory factory = null;
Session session = null;
try
{
factory = new Configuration().configure().buildSessionFactory();
session = factory.openSession();
Transaction tx = session.beginTransaction();
Department department = (Department) session.load(Department.class, 2l);
tx.commit();
}
结果:因为没有用到Department中任何信息,所以根本没有sql语句
6)get和load
1.load方法是懒加载,在用到类中信息的时候才会去数据库中加载
2.get方法是立即执行sql,从数据库中去的数据
注意:如果类和其他类有一对多等关联关系,那么其他类是否懒加载,和本类是否懒加载无关系,可以单独设置
实例:
<class name="cn.com.cpf.pojo.Department" table="t_department" lazy="false">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="name"/>
<set name="employees" inverse="false" lazy="true">
<key column="departmentId"/>
<one-to-many class="cn.com.cpf.pojo.Employee" />
</set>
</class>
factory = new Configuration().configure().buildSessionFactory();
session = factory.openSession();
Transaction tx = session.beginTransaction();
Department department = (Department) session.load(Department.class, 2l);
tx.commit();
结果为:Hibernate: select department0_.id as id1_3_0_, department0_.name as name2_3_0_ from t_department department0_ where department0_.id=?
访问其他类信息:
factory = new Configuration().configure().buildSessionFactory();
session = factory.openSession();
Transaction tx = session.beginTransaction();
Department department = (Department) session.load(Department.class, 2l);
department.getEmployees().size();
结果为:Hibernate: select department0_.id as id1_3_0_, department0_.name as name2_3_0_ from t_department department0_ where department0_.id=?
Hibernate: select employees0_.departmentId as departme3_3_0_, employees0_.id as id1_4_0_, employees0_.id as id1_4_1_, employees0_.name as name2_4_1_, employees0_.departmentId as departme3_4_1_ from t_employee employees0_ where employees0_.departmentId=?
7)本类中其他类的lazy属性还可以设置为extra,也就是根据访问的信息来生成不同的sql,而不是将整个类加载
<class name="cn.com.cpf.pojo.Department" table="t_department" lazy="false">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="name"/>
<set name="employees" inverse="false" lazy="extra">
<key column="departmentId"/>
<one-to-many class="cn.com.cpf.pojo.Employee" />
</set>
</class>
factory = new Configuration().configure().buildSessionFactory();
session = factory.openSession();
Transaction tx = session.beginTransaction();
Department department = (Department) session.load(Department.class, 2l);
department.getEmployees().size();
结果为:Hibernate: select department0_.id as id1_3_0_, department0_.name as name2_3_0_ from t_department department0_ where department0_.id=?
Hibernate: select count(id) from t_employee where departmentId =?
因为只是查询数量,所以使用count8) 有可能只有此处需要立即加载,而其他地方都使用懒加载,也就是立即加载懒加载的对象
<class name="cn.com.cpf.pojo.Department" table="t_department" lazy="true">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="name"/>
<set name="employees" inverse="false" lazy="true">
<key column="departmentId"/>
<one-to-many class="cn.com.cpf.pojo.Employee" />
</set>
</class>
factory = new Configuration().configure().buildSessionFactory();
session = factory.openSession();
Transaction tx = session.beginTransaction();
Department department = (Department) session.load(Department.class, 2l);
department.getEmployees();
tx.commit();
结果为:Hibernate: select department0_.id as id1_3_0_, department0_.name as name2_3_0_ from t_department department0_ where department0_.id=?
factory = new Configuration().configure().buildSessionFactory();
session = factory.openSession();
Transaction tx = session.beginTransaction();
Department department = (Department) session.load(Department.class, 2l);
Hibernate.initialize(department.getEmployees());
tx.commit();
结果为:Hibernate: select department0_.id as id1_3_0_, department0_.name as name2_3_0_ from t_department department0_ where department0_.id=?
Hibernate: select employees0_.departmentId as departme3_3_0_, employees0_.id as id1_4_0_, employees0_.id as id1_4_1_, employees0_.name as name2_4_1_, employees0_.departmentId as departme3_4_1_ from t_employee employees0_ where employees0_.departmentId=?
9) 懒加载异常
1>原因:真正获取数据时,session已经关闭
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
2>解决方法:
1.不用懒加载
2.在session关闭前获得数据
3.使用Hibernate.initialize来立即获得需要的对象