对于hibernate的延迟加载,就是对一个对象加载的时候,不去加载他的相关的对象。
以立即加载中的student和team为例子:
如果student延迟加载team,team立即加载student
Session session = SessionUtil.getSession();
Transaction tran = session.beginTransaction();
Student stu = (Student)session.get(Student.class, 2);
tran.commit();
session.close();
//关闭 SESSION
System.out.println(stu.getName());
System.out.println(stu.getTeamID().getName());
System.out.println(stu.getTeamID().getStudents().size());
这样操作会报错,原因是学生对班级是延迟加载,在SESSION关闭以后,班级对象是加载不到的。
修改方式1:
Session session = SessionUtil.getSession();
Transaction tran = session.beginTransaction();
Student stu = (Student)session.get(Student.class, 2);
tran.commit();
session.close();
//打开另外一个SESSION,然后让他重新关联班级对象
Session session2 = SessionUtil.getSession();
Transaction tran2 = session2.beginTransaction();
session2.update(stu.getTeamID());
System.out.println(stu.getName());
System.out.println(stu.getTeamID().getName());
System.out.println(stu.getTeamID().getStudents().size());
tran2.commit();
session2.close();
打印:
1.Hibernate: select student0_.ID as ID1_0_, student0_.Name as Name1_0_, student0_.TeamID as TeamID1_0_ from test.student student0_ where student0_.ID=?
2.tuping
3.Hibernate: select team0_.ID as ID0_0_, team0_.Name as Name0_0_ from test.team team0_ where team0_.ID=?
4.二中
5.Hibernate: select students0_.teamID as teamID1_, students0_.ID as ID1_, students0_.ID as ID1_0_, students0_.Name as Name1_0_, students0_.TeamID as TeamID1_0_ from test.student students0_ where students0_.teamID=?
6.2
对于1的解释:通过开启另外一个SESSION重新关联班级学生对象,因为学生对班级是延迟的,所以加载学生的时候不加载班级。
对于2的解释:打印学生姓名
对于3的解释:因为要打印班级的名称,所以重新关联班级信息,发出查询语句。
对于4的解释:打印班级名称。
对于5的解释:然后查询班级中学生的个数,发出查询语句,因为在1出关联学生对象的时候,已经将一个学生放到内存中了,所以在查询学生人数的时候只发送另外一条去查询剩余的学生人数。这也是HIBERNATE的高明的地方。内存中有的数据就不再发送SQL去查询了。
对于6的解释:打印班级人数2.
2.修改方式2(黑体字部分是多加的语句)
Session session = SessionUtil.getSession();
Transaction tran = session.beginTransaction();
Student stu = (Student)session.get(Student.class, 2);
tran.commit();
session.close();
Session session2 = SessionUtil.getSession();
Transaction tran2 = session2.beginTransaction();
session2.update(stu.getTeamID());
Hibernate.initialize(stu.getTeamID());
Hibernate.initialize(stu.getTeamID().getStudents());
System.out.println(stu.getName());
System.out.println(stu.getTeamID().getName());
System.out.println(stu.getTeamID().getStudents().size());
tran2.commit();
session2.close();
通过hibernate.initialize的方法重新将team进行关联,这个方法仅仅初始化一个代理对象或集合,并不能保证代理或集合内部嵌套的代理,所以初始化班级代理并不初始化学生集合,所以要写另外一条语句对学生集合进行初始化。
打印:
1.Hibernate: select student0_.ID as ID1_0_, student0_.Name as Name1_0_, student0_.TeamID as TeamID1_0_ from test.student student0_ where student0_.ID=?
2.Hibernate: select team0_.ID as ID0_0_, team0_.Name as Name0_0_ from test.team team0_ where team0_.ID=?
3.Hibernate: select students0_.teamID as teamID1_, students0_.ID as ID1_, students0_.ID as ID1_0_, students0_.Name as Name1_0_, students0_.TeamID as TeamID1_0_ from test.student students0_ where students0_.teamID=?
4.tuping
5.二中
6.2
该打印语句跟修改的第一种方式是一样的只是在加载的时候顺序不一样。原因是通过initial方法,将初始化班级以及班级中的学生数量。所以一开始就将对象初始化完毕,在打印的时候就不再发出查询语句了。
session.update方法的作用主要有两点:
1.更新对象
2.将脱管对象和SESSION进行关联。