spring Junit下的延迟加载问题(Hibernate)
2016-04-20 10:16
513 查看
在使用spring管理junit下的Hibernate时,会出现org.hibernate.LazyInitializationException: could not initialize proxy - no Session,原因大家都知道,当session关闭后,你访问对象中的延迟加载属性,都会报session已关闭的错误。解决办法一般有四种:
1、在关闭session之前,使用Hibernate.initialize(Object proxy)强制加载
2、在关闭session之前,对延迟属性进行一次get访问
3、使用hql预加载,一般会用到fetch语句
4、hbm映射文件中,让集合或对象属性的
lazy=false
以面四种方式,如果用在与spring整合后的hibernate中,方式1、方式2可能不太好合,除非你使用模板的execute回调,在项目中是如何解决的呢?采用openSessionInView过滤器,该过滤器非常有效,会保证在同一次请求中,打开一个session,在当次请求中,打开不会关闭(具体底
层实现用到了ThreadLocal类),请求结束后spring会妥善处理好session的。有了 openSessionInView,我们几乎看不到延迟加载错误了,但是,在开发中我们又遇到了另一个严峻的问题,我们在业务层的测试代码中,却无法开 启openSessionInView,这就出现了,在action及页面中都正常的代码,拿到junit测试中却无法通过,这该如何是好?解决办法如
下:
在你的测试类中的setUp和tearDown中,加上下面的代码,注意,要把sessionFactory定义到外面。
private SessionFactory sessionFactory;
public void setUp() throws Exception {
sessionFactory = (SessionFactory) beanFactory.getBean("sessionFactory");
Session s = sessionFactory.openSession();
TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(s));
}
public void tearDown() throws Exception {
SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
Session s = holder.getSession();
s.flush();
TransactionSynchronizationManager.unbindResource(sessionFactory);
}
上面的代码是纯junit下的测试,如果你用了AbstractTransactionalSpringContextTests作为测试基类,sessionFactory的初始化就没有这么复杂了,直接由spring注入进来即可。
1、在关闭session之前,使用Hibernate.initialize(Object proxy)强制加载
2、在关闭session之前,对延迟属性进行一次get访问
3、使用hql预加载,一般会用到fetch语句
4、hbm映射文件中,让集合或对象属性的
lazy=false
以面四种方式,如果用在与spring整合后的hibernate中,方式1、方式2可能不太好合,除非你使用模板的execute回调,在项目中是如何解决的呢?采用openSessionInView过滤器,该过滤器非常有效,会保证在同一次请求中,打开一个session,在当次请求中,打开不会关闭(具体底
层实现用到了ThreadLocal类),请求结束后spring会妥善处理好session的。有了 openSessionInView,我们几乎看不到延迟加载错误了,但是,在开发中我们又遇到了另一个严峻的问题,我们在业务层的测试代码中,却无法开 启openSessionInView,这就出现了,在action及页面中都正常的代码,拿到junit测试中却无法通过,这该如何是好?解决办法如
下:
在你的测试类中的setUp和tearDown中,加上下面的代码,注意,要把sessionFactory定义到外面。
private SessionFactory sessionFactory;
public void setUp() throws Exception {
sessionFactory = (SessionFactory) beanFactory.getBean("sessionFactory");
Session s = sessionFactory.openSession();
TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(s));
}
public void tearDown() throws Exception {
SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
Session s = holder.getSession();
s.flush();
TransactionSynchronizationManager.unbindResource(sessionFactory);
}
上面的代码是纯junit下的测试,如果你用了AbstractTransactionalSpringContextTests作为测试基类,sessionFactory的初始化就没有这么复杂了,直接由spring注入进来即可。
相关文章推荐
- JAVA反射机制详解
- Ubuntu启动eclipse问题
- Ubuntu启动eclipse问题
- 自定义View:关于Caused by: java.lang.NoSuchMethodException异常
- Java线程同步小陷阱,你掉进去过吗?
- java.util.concurrent.locks与synchronized及其异同
- 避免Java应用中NullPointerException的技巧和最佳实践
- java for循环里面执行sql语句操作,有效结果只有一次,只执行了一次sql mybatis 循环执行update生效一次 实际只执行一次
- eclipse配置
- Java多线程:线程同步与关键字synchronized
- java设计模式之单例模式的七种写法
- java -jar Test.jar找不到main class问题
- Java 8 新特性:Lambda 表达式之方法引用(Lambda 表达式补充版)
- Spring之初识JavaBean
- java并发-原子性
- 【java】关于interface成员变量的修饰符
- java web统计当前访问用户数量
- 生成MyEclipse6.5&7.5&8.0注册码的java源码 生成MyEclipse6.5&7.5&8.0注册码的java源码 MyEclipseKeyGen MyEclipse6.5&7.5&
- JAVA简单工厂模式
- spring中@ResponseBody和@JsonProperty作用