public void testload2() {
Session session = null;
Group group = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
group = (Group) session.load(Group.class, 1);
[color=red]
System.out.println("group.name=" + group.getName());[/color]
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
} finally {
HibernateUtils.closeSession(session);
}
// could not initialize proxy - the owning Session was closed
// LazyInitializationException:
[color=brown]System.out.println("group.name=" + group.getInfo());[/color]
}
大家帮我看看,如果加上System.out.println("group.name=" + group.getName())这段代码就不会抛出LazyInitializationException,如果不加就会出现LazyInitializationException,不知道为什么,不都关闭了session了吗?
先学习:
缓存是位于应用程序与物理数据源之间,用于临时存放复制数据的内存区域,目的是为了减少应用程序对物理数据源访问的次数,从而提高应用程序的运行性能.
Hibernate在查询数据时,首先到缓存中去查找,如果找到就直接使用,找不到的时候就会从物理数据源中检索,所以,把频繁使用的数据加载到缓存区后,就可以大大减少应用程序对物理数据源的访问,使得程序的运行性能明显的提升.
Hibernate缓存分类:
Session缓存,一级缓存.
SessionFactory的缓存分为内置缓存和外置缓存.内置缓存中存放的是SessionFactory对象的一些集合属性包含的数据(映射元素据及预定义SQL语句等),对于应用程序来说,它是只读的.外置缓存中存放的是数据库数据的副本,其作用和一级缓存类似.二级缓存除了以内存作为存储介质外,还可以选用硬盘等外部存储设备.
Hibernate的缓存范围
Hibernate的一级缓存和二级缓存都位于均位于持久层,且均用于存放数据库数据的副本,最大的区别就是缓存的范围各不一样.
缓存的范围分为3类:
1.事务范围
事务范围的缓存只能被当前事务访问,每个事务都有各自的缓存,缓存内的数据通常采用相互关联的对象形式.缓存的生命周期依赖于事务的生命周期,只有当事务结束时,缓存的生命周期才会结束.事务范围的缓存使用内存作为存储介质,一级缓存就属于事务范围.
2.应用范围
应用程序的缓存可以被应用范围内的所有事务共享访问.缓存的生命周期依赖于应用的生命周期,只有当应用结束时,缓存的生命周期才会结束.应用范围的缓存可以使用内存或硬盘作为存储介质,二级缓存就属于应用范围.
3.集群范围
在集群环境中,缓存被一个机器或多个机器的进程共享,缓存中的数据被复制到集群环境中的每个进程节点,进程间通过远程通信来保证缓存中的数据的一致,缓存中的数据通常采用对象的松散数据形式.
我的理解是,
加上System.out.println("group.name=" + group.getName())这段代码,相对于开启了二级缓存。即使session关闭,根据lazy loading,还是能从二级cache中找到。所以不会出错了。
欢迎指正。
看看详解吧
http://www.blogjava.net/zygcs/archive/2009/03/20/261017.html
正是因为你session已经关闭了,所以你去拿一些延迟加载的值的时候就会报错。为了避免这个错误,需要使用Hibernate.init()先手动加载lazy=true的字段。
你肯定是在业务层拿数据的时候报出来的,比如group.getUser().由于session已经结束,user又是延迟加载,报错。
查询数据的确不需要事务,多于的。