最近的新项目想要做一件这样的事情:一个定期任务做一些业务逻辑与数据库操作。这个任务需要定时启动完成。
我不想将定期任务新建一个后台java然后用bat进行处理,想直接将任务与web环境整合在一起。开始的时候自己编写了一个listener,在contextInitialized的地方 实例化一个timetask来做相应的事情。结果在task中想要进行hibernate调用的时候报错了,开始时候代码是这样的
web.xml中加入监听器
<listener> <listener-class> com.taikang.imc.web.SmsTaskLoaderListener </listener-class> </listener>
SmsTaskLoaderListener为监听器类
//在contextInitialized中加入 springContext = WebApplicationContextUtils .getWebApplicationContext(arg0.getServletContext()); if(log.isDebugEnabled()){ if(springContext!=null) log.debug("Spring ApplicationContext 初始化成功!"); else log.debug("Spring ApplicationContext 初始化失败!"); } ReceiveSmsTask rst = new ReceiveSmsTask(); rst.init(springContext); receiveScanner.scheduleAtFixedRate(rst, 2000, 6 * 1000);
ReceiveSmsTask为任务类。
后来运行中报错:No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here 大意是监听器中不存在Session,并且事务有配置问题。
查证了自己配置文件的事务部分,并无问题,整个WEB环境也能够正常运行,真是百思不得其解。
后来网上搜索,仔细查证,发现我的hibernate使用时候的文件中有这样的代码
public Session getSession() { return sessionFactory.getCurrentSession(); // return sessionFactory.openSession(); }
然后有人说:把其中的getCurrentSession改成openSession就可以使用,当没有事物启动的时候getCurrentSession是无法创建Session的。
参考:http://www.iteye.com/topic/87035
opensession是从sessionfactory得到一个新的session,所以可以使用,而getCurrentSession是从当前线程 中得到事务开始时创建transaction的那个session,而你的事务没有能正确的启动,所以并没有一个session绑定到当前线程,所以你也 得不到。
我的最终的解决办法是通过注解给我的service加上事务即可:@Transactional
于是给自己的
ReceiveSmsTask加上@Transactional 一路畅通