junit测试之hiberante延迟加载问题
很多新手都会遇到的hibernate session关闭时的延迟加载错误,我想原因大家都知道,当session关闭后,你去访问对象中的延迟加载属性,都会报session已关闭的错误。解决办法一般有四种:
1、hbm映射文件中,让集合或对象属性的lazy=false
2、在关闭session之前,使用Hibernate.initialize(Objectproxy)强制加载
3、在关闭session之前,对延迟属性进行一次get访问
4、使用hql预加载,一般会用到fetch语句
以面四种方式,如果用在与spring整合后的hibernate中,方式2、方式3可能不太好合,除非你使用模板的execute回调,那么我们在项目中是如何解决的呢?
采用openSessionInView过滤器,该过滤器非常有效,会保证在同一次请求中,打开一个session,在当次请求中,打开不会关闭(具体底层实现用到了ThreadLocal类,有兴趣的可以到网上搜一下),请求结束后spring会妥善处理好session的。有了openSessionInView,我们几乎看不到延迟加载错误了,但是,在开发中我们又遇到了另一个严峻的问题,我们在业务层的测试代码中,去无法开启openSessionInView,这就出现了,在action及页面中都正常的代码,拿到junit测试中却无法通过,这该如何是好?解决办法如下:
在你的测试类中的setUp和tearDown中,加上下面的代码,注意,要把sessionFactory定义到外面。
privateSessionFactorysessionFactory;
publicvoidsetUp()throwsException{
sessionFactory=(SessionFactory)beanFactory.getBean("sessionFactory");
Sessions=sessionFactory.openSession();
TransactionSynchronizationManager.bindResource(sessionFactory,newSessionHolder(s));
}
publicvoidtearDown()throwsException{
SessionHolderholder=(SessionHolder)TransactionSynchronizationManager.getResource(sessionFactory);
Sessions=holder.getSession();
s.flush();
TransactionSynchronizationManager.unbindResource(sessionFactory);
}
上面的代码是纯junit下的测试,如果你用了AbstractTransactionalSpringContextTests作为测试基类,sessionFactory的初始化就没有这么复杂了,直接由spring注入进来即可。