问题描述
各位好,我遇到一个我觉得不可思议的问题,请高人指点。首先我建了一个操作实体类的DAO对象,其中一个函数代码如下:内容很简单,就是从数据库中取出表中有多少条记录publicintgetCount(){Sessionsession=HibernateUtil.getSessionFactory().openSession();intcount=((Long)session.createQuery("selectcount(*)fromAnnounce").uniqueResult()).intValue();if(session.isOpen()&&session!=null)session.close();returncount;}
然后我再action的一个方法中调用这个方法。publicStringaddAnnounce(){//初始化adminservice对象AnnounceServiceas=newAnnounceService();Announcea=newAnnounce();a.setAContent(this.announcecontent);a.setATitle(this.announcetitle);a.setAAuthor((String)ActionContext.getContext().getSession().get("admin"));a.setATime(newDate());as.save(a);System.out.println(newTechnicDAO().getCount());//在保存之后,打印出共有多少条记录return"addannounce";}
在这里出了严重问题,无论我怎么添加记录,打印出的都是第一次打印的数据。比如第一次打印出10,我又添加两条,还是打印10,无论怎么添加,都是10.除非重新部署或者重启容器。但是我在一个jsp页面中做了如下测试<%out.print(newAnnounceDAO().getCount());System.out.println(newAnnounceDAO().getCount());%>在这个jsp里,却可以始终与数据库内的记录完全对应。我实在是很费解,struts到底是怎么工作的,会搞成这个样子?有什么解决方法没有?
解决方案
解决方案二:
as.save(a);这里用的是hibernate的save吧,save之后需要用session.flush();来刷到数据库中如果再不好用,就请加上事务处理
解决方案三:
事务处理在一个过滤器中都已经进行了,储存方面没有问题。
解决方案四:
引用2楼aoliwen521的回复:
事务处理在一个过滤器中都已经进行了,储存方面没有问题。
又一个说自己没问题的人你提到了过滤器,那么可见action方法addAnnounce()是在一个是事务当中的,你想一下,还能得到吗如果想得到,那么需要设置hibernate的autocommit为true,这样用flush()才能好用,否则就请你提交事务后再来获取count
解决方案五:
save好还没写数据库那,要COMMIT或者FLUSH把
解决方案六:
Sessionsession=null;Transactiontx=null;try{//从当前线程中获得sessionsession=HibernateUtil.getThreadLocalSession();//开启事务tx=session.beginTransaction();//执行请求方法chain.doFilter(request,response);//提交事务tx.commit();}catch(Exceptione){//捕获到错误回滚事务if(tx!=null)tx.rollback();thrownewRuntimeException(e.getMessage(),e);}finally{//关闭sessionHibernateUtil.closeSession();}
过滤器是这样子的。确实是在提交之前取得count。但是即使是这样,第二次再访问这个方法,是否也应该是获取前一次的count。为什么会一直保持一个值不变呢?
解决方案七:
不知道HibernateUtil怎么写的,如果是用hibernate那个HibernateSessionFactory的话,只需要用HibernateSessionFactory.getSession()来获取当前线程中的session,如果没有则创建一个session,再把这个session放入threadlocal这样就不需要再进行HibernateUtil.getSessionFactory().openSession();if(session.isOpen()&&session!=null)session.close();真不知道session关闭之后,事务怎么提交,呵呵回答完毕
解决方案八:
HibernateUtil的getThreadLocalSession()方法是从县城中获取session,如果没有则创建一个。而getSessionFactory().openSession()我是想再另外通过sessionFactory创建一个session和线程中session的无关,请问高人,难道这两方法创建的session仍然是同一个?或者出现什么故障了?
解决方案九:
而且奇怪的是在jsp的页面中调用同样的newAnnounce().getCount()方法,打印的出的数据和数据库里的一致。唯独这个action中的,无论添加多少个,打印出的始终是第一次的数据。而这个时候jsp中显示的却可以更新。
解决方案十:
多谢楼上的几位高人,问题有了新的进展。我这回直接将代码写道action中,如果代码是:就没有什么反应,始终不变。publicStringaddAnnounce(){//初始化adminservice对象AnnounceServiceas=newAnnounceService();Announcea=newAnnounce();a.setAContent(this.announcecontent);a.setATitle(this.announcetitle);a.setAAuthor((String)ActionContext.getContext().getSession().get("admin"));a.setATime(newDate());as.save(a);Sessionsession=HibernateUtil.getSessionFactory().openSession();intcount=((Long)session.createQuery("selectcount(*)fromAnnounce").uniqueResult()).intValue();if(session.isOpen()&&session!=null)session.close();System.out.println("打印出来:"+count);return"addannounce";}
但是如果是这样,把session的获得改为getThreadLocalSession()则就可以出现更新的数据。publicStringaddAnnounce(){//初始化adminservice对象AnnounceServiceas=newAnnounceService();Announcea=newAnnounce();a.setAContent(this.announcecontent);a.setATitle(this.announcetitle);a.setAAuthor((String)ActionContext.getContext().getSession().get("admin"));a.setATime(newDate());as.save(a);Sessionsession=HibernateUtil.getThreadLocalSession();intcount=((Long)session.createQuery("selectcount(*)fromAnnounce").uniqueResult()).intValue();System.out.println("打印出来:"+count);return"addannounce";}
请高人给我讲讲背后的原因,谢谢。
解决方案十一:
新手上路,学习,接分,顶
解决方案十二:
staticSessiongetSession()这个是静态方法,类共享的,想要关闭那有那么容易呀。//这个是线程独占,你那个过滤器在这个线程的生命周期到END的时候就起作用了。sava执行完毕,生命over,过滤器完成commit。publicstaticSessiongetThreadLocalSession()throwsHibernateException{Sessionsession=(Session)threadLocal.get();if(session==null||!session.isOpen()){if(sessionFactory==null){rebuildSessionFactory();}session=(sessionFactory!=null)?sessionFactory.openSession():null;threadLocal.set(session);}returnsession;}