Hibernate lazy策略:延迟加载、懒加载。
代理的概念:只有真正使用该对象的时候才会创建。
Lazy在hibernate上:在真正使用的时候才会发出sql查询。
实现原理:采用第三方库cglib,对类生成代理类。代理可以控制源对象,并且可以对源对象的功能进行增强。
Cglib和jdk动态代理的区别:
1,cglib能够对类进行代理,jdk动态代理只能对实现了接口的类进行代理。
2,Jdk动态代理类和原类实现相同的接口
3,Cglib 代理类继承原类,生成一个子类。
Lazy在hibernate中的使用地方:可以取值true或false。
* <class>标签,可以取值true或false。默认为true。
* <property> 标签,可以取值true或false。很少用。
* 集合<set><list>,可以取值true、fasle或extra。默认为true。
* <one-to-one> 、<many-to-one> 单端关联上,可以取值false、proxy或noproxy。默认proxy
Load支持lazy,get不支持lazy。并且Load的时候只会加载普通属性,集合不会加载
Lazy的生命周期跟session一样,session关闭,lazy也失效。
Class上的lazy策略:影响的范围是普通属性的加载,对集合不起作用。
session.beginTransaction();
//不会发出sql
Group group = (Group)session.load(Group.class, 1);
//不会发出sql
System.out.println("group.id=" + group.getId());
//会发出sql
System.out.println("group.name=" + group.getName());
session.getTransaction().commit();
Group group = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
group = (Group)session.load(Group.class, 1);
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
//不能正确输出,抛出LazyInitializationException 异常,因为session已经关闭
//hibernate支持lazy策略只有在session打开状态下有效
System.out.println("group.name=" + group.getName());
集合上的lazy:建议使用extra,因为会发出智能sql。
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
for (Iterator iter=students.iterator(); iter.hasNext();) {
Student student = (Student)iter.next();
System.out.println("student.name=" + student.getName());
}
session.getTransaction().commit();
设置<class>标签上的lazy=false
session.beginTransaction();
//会发出sql
Classes classes = (Classes)session.load(Classes.class, 1);
//不会发出sql
System.out.println("classes.name=" + classes.getName());
//不会发出sql,class上的lazy不影响集合
Set students = classes.getStudents();
//会发出sql
for (Iterator iter=students.iterator(); iter.hasNext();) {
Student student = (Student)iter.next();
System.out.println("student.name=" + student.getName());
}
session.getTransaction().commit();
设置集合上的lazy=false,默认为true。
session.beginTransaction();
//不会发出sql
Classes classes = (Classes)session.load(Classes.class, 1);
//会发出sql,会发出两条sql分别加载Classes和Student
System.out.println("classes.name=" + classes.getName());
//不会发出sql
Set students = classes.getStudents();
//不会发出sql
for (Iterator iter=students.iterator(); iter.hasNext();) {
Student student = (Student)iter.next();
System.out.println("student.name=" + student.getName());
}
session.getTransaction().commit();
设置集合上的lazy=extra
1,跟lazy=true效果一样。
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
for (Iterator iter=students.iterator(); iter.hasNext();) {
Student student = (Student)iter.next();
System.out.println("student.name=" + student.getName());
}
session.getTransaction().commit();
2,发出智能sql
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,发出一条比较智能的sql,直接发出count()sql
System.out.println("student.count=" + students.size());
session.getTransaction().commit();
单端关联上的lazy:可以取值false,proxy,noproxy,默认proxy,noproxy采用字节码,需要增强工具支持。
单端关联上默认lazy属性:跟集合一样
session.beginTransaction();
//不会发出sql
User user = (User)session.load(User.class, 1);
//会发出sql
System.out.println("user.name=" + user.getName());
//不会发出sql
Group group = user.getGroup();
//会发出sql
System.out.println("group.name=" + group.getName());
session.getTransaction().commit();
单端关联上lazy=false:跟集合一样
session.beginTransaction();
//不会发出sql
User user = (User)session.load(User.class, 1);
//会发出sql,发出两条sql分别加载User和Group
System.out.println("user.name=" + user.getName());
//不会发出sql
Group group = user.getGroup();
//不会发出sql
System.out.println("group.name=" + group.getName());
session.getTransaction().commit();
class上lazy=fasle,单端关联上lazy=proxy
class上的lazy 不会影响到单端关联上的lazy。
session.beginTransaction();
//会发出sql
User user = (User)session.load(User.class, 1);
//不会发出sql
System.out.println("user.name=" + user.getName());
//不会发出sql
Group group = user.getGroup();
//会发出sql
System.out.println("group.name=" + group.getName());
session.getTransaction().commit();