这里使用的框架是spring、jpa和hibernate的整合,针对一个请求中扩大session的范围可参考这个做法,在web.xml配置文件加入,主要要在核心过滤器前面,这里加的过滤器是openEntityManagerInViewFilter,因为使用的是spring jpa的session会话:
<!-- 解决懒加载 no session(会话无效)问题 -->
<filter>
<filter-name>openEntityManagerInViewFilter</filter-name>
<filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>openEntityManagerInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
至于多线程下,通过扩大session范围来也无法解决时,则可在线程启动的run方法中绑定JPA EntityManager的session,才能保证能在新的线程中使用事务和延迟加载等功能,这里报错应该是请求发起,开多个线程,线程在异步执行,这时请求已经完成,session关闭,那多线程下再获取之前的懒加载数据就会报错提示no Session,解决代码参考如下:
//先在需要使用的类通过注解的方式或其他方式注入获取JPA实体管理器工厂,再传入线程
@PersistenceUnit
private EntityManagerFactory emFactory;
//例如:打开线程进行处理,传入工厂
Thread thread = new Thread(emFactory);
thread.start();
//在启动线程的run方法绑定session会话
public void run(){
//在线程中添加数据库Session
boolean participate = false;
if (TransactionSynchronizationManager.hasResource(emFactory)) {
participate = true;
}else{
try {
EntityManager em = emFactory.createEntityManager();
EntityManagerHolder emHolder = new EntityManagerHolder(em);
TransactionSynchronizationManager.bindResource(emFactory, emHolder);
}
catch (PersistenceException ex) {
throw new DataAccessResourceFailureException("Could not create JPA
EntityManager at Thread", ex);
}
}
//---------------------------------------
//你的业务代码
//-----------------------------------------
//如果添加过数据库Session,在结束时关闭Session
if(!participate){
EntityManagerHolder emHolder = (EntityManagerHolder)
TransactionSynchronizationManager.unbindResource(emFactory);
EntityManagerFactoryUtils.closeEntityManager(emHolder.getEntityManager());
}
}