本例子表为 Students 表和Classes 表 其中 Students 表与Classes表的管理关系为单向N-1
单向N-1检索:
在N的一方加入 lazy="false" ,即在做查询时 将与N关联的表全部查询出来(立即检索)
代码:
Students stu = (Students) session.get(Students.class, 1); System.out.println(stu.getAddress());
控制台显示的sql如下:
Hibernate: select students0_.STUID as STUID1_1_0_, students0_.NAME as NAME2_1_0_, students0_.ADDRESS as ADDRESS3_1_0_, students0_.CLASSID as CLASSID4_1_0_ from STUDENTS students0_ where students0_.STUID=? Hibernate: select classes0_.CLASSID as CLASSID1_0_0_, classes0_.CLASSNAME as CLASSNAM2_0_0_ from CLASSES classes0_ where classes0_.CLASSID=? wangzhe
即我在只查询一个student的属性值时,它也将我的class表做了一个初始化,这种策略对于hibernate性能来说是很不好的。
懒加载问题:
Students stu = (Students) session.get(Students.class, 1); System.out.println(stu.getAddress()); session.close(); //此处 session关闭 System.out.println(stu.getClasses().getClassName());
控制台sql:
Hibernate: select students0_.STUID as STUID1_1_0_, students0_.NAME as NAME2_1_0_, students0_.ADDRESS as ADDRESS3_1_0_, students0_.CLASSID as CLASSID4_1_0_ from STUDENTS students0_ where students0_.STUID=? Hibernate: select classes0_.CLASSID as CLASSID1_0_0_, classes0_.CLASSNAME as CLASSNAM2_0_0_ from CLASSES classes0_ where classes0_.CLASSID=? wangzhe zhihuei
由上可以看出:lazy=false 就是关闭掉了懒加载 ,所以这个是解决懒加载异常的策略之一,但是,这个策略却
极其消耗性能 。所以 我们一般在N的一方不去定义 lazy=false;顺便说一句 lazy="false"是没有懒加载异常的
单向N-1的检索策略:
N-1 lazy ="proxy"(即单端N的一端默认的加载策略) 即生成代理 就是延时加载
代码如下:
Students stu = (Students) session.get(Students.class, 1); System.out.println(stu.getAddress());
控制台sql如下:
Hibernate: select students0_.STUID as STUID1_1_0_, students0_.NAME as NAME2_1_0_, students0_.ADDRESS as ADDRESS3_1_0_, students0_.CLASSID as CLASSID4_1_0_ from STUDENTS students0_ where students0_.STUID=? wangzhe
我们可以发现 .并没有初始化对应的classes 表 ,此时 classes对象的一个代理对象,
当session关闭时.代码如下:
Students stu = (Students) session.get(Students.class, 1); System.out.println(stu.getAddress()); session.close(); //此处 session关闭 System.out.println(stu.getClasses().getClassName());
会报一个懒加载异常
懒加载异常解决办法如下:
典型应用:
在hibernate 与spring整合时 有一张学生表与班级表 ,当我们要显示学生的的所有信息的时候用显示所有的班级名称,如果我们以默认的懒加载策略(lazy="proxy") 会报懒加载错误 ,因为此时班级对象是个代理(班级对象没有做初始化工作)而此时session却关闭了,所以会报 no -session........的懒加载异常。
那怎么解决呢?
有4种办法可以解决:
1.关闭懒加载(lazy=false) 就是 我在加载Student对象的时候就把classes对象的初始化工作完成,代码如上. 问题是这样极大的消耗我们的查询性能.所以不推荐 甚至这种办法应该舍弃掉。
2.在web.xml 里配置一个过滤器 ,即OpensessioninView 。 顾名思义 就是在渲染视图的时候session是一直开着的即当前事物方法结束之后 session 也一直开着 直到 视图渲染完成 。问题是,这会导致session混乱
在做高并发量小的项目时可以.但是高并发量就会导致不知预想的错误,所以 不推荐
3.改变抓取策略 我们在做本地sql的时候 会用到 left outer join inner jion等等一系列的连接查询
来查询出关联的表的数据 所有 我们可以在hql语句 定义一个left outer join 的连接查询
代码如下:
FROM STUDENTS s LEFT OUTER JOIN FETCH s.classes;
也可以在N的一端的配置文件中指定抓取策略 即fetch="join" 但是我们一般不要在配置文件中去配置
原因是 只要我们一查询 STUDENTS 表的属性时 它都会发出这样的左外连接语句.
4.在session关闭之前 就做一个初始化工作:
如 Classes classes =Students的引用.getClasses();
但这个初始化工作视具体情况而定 .
单向多对一与双向多对一是一样的 。
单向1-N与双向1对多也是一样的 。只不过在单向或双向中 它的默认检索策略为 lazy="true"即开启懒加载。