各位好,我遇到一个我觉得不可思议的问题,请高人指点。
首先我建了一个操作实体类的DAO对象,其中一个函数代码如下:
内容很简单,就是从数据库中取出表中有多少条记录 public int getCount(){
Session session = HibernateUtil.getSessionFactory().openSession();
int count = ((Long)session.createQuery("select count(*) from Announce").uniqueResult()).intValue();
if(session.isOpen() && session != null)session.close();
return count;
}然后我再action的一个方法中调用这个方法。public String addAnnounce(){
//初始化adminservice对象
AnnounceService as=new AnnounceService();
Announce a=new Announce();
a.setAContent(this.announcecontent);
a.setATitle(this.announcetitle);
a.setAAuthor((String)ActionContext.getContext().getSession().get("admin"));
a.setATime(new Date());
as.save(a);
System.out.println(new TechnicDAO().getCount()); //在保存之后,打印出共有多少条记录
return "addannounce";
}在这里出了严重问题,无论我怎么添加记录,打印出的都是第一次打印的数据。
比如第一次打印出 10 ,我又添加两条,还是打印10,无论怎么添加,都是10.除非重新部署或者重启容器。但是我在一个jsp页面中做了如下测试
<%
out.print(new AnnounceDAO().getCount());
System.out.println(new AnnounceDAO().getCount());
%>在这个jsp里,却可以始终与数据库内的记录完全对应。我实在是很费解,struts到底是怎么工作的,会搞成这个样子?有什么解决方法没有?
首先我建了一个操作实体类的DAO对象,其中一个函数代码如下:
内容很简单,就是从数据库中取出表中有多少条记录 public int getCount(){
Session session = HibernateUtil.getSessionFactory().openSession();
int count = ((Long)session.createQuery("select count(*) from Announce").uniqueResult()).intValue();
if(session.isOpen() && session != null)session.close();
return count;
}然后我再action的一个方法中调用这个方法。public String addAnnounce(){
//初始化adminservice对象
AnnounceService as=new AnnounceService();
Announce a=new Announce();
a.setAContent(this.announcecontent);
a.setATitle(this.announcetitle);
a.setAAuthor((String)ActionContext.getContext().getSession().get("admin"));
a.setATime(new Date());
as.save(a);
System.out.println(new TechnicDAO().getCount()); //在保存之后,打印出共有多少条记录
return "addannounce";
}在这里出了严重问题,无论我怎么添加记录,打印出的都是第一次打印的数据。
比如第一次打印出 10 ,我又添加两条,还是打印10,无论怎么添加,都是10.除非重新部署或者重启容器。但是我在一个jsp页面中做了如下测试
<%
out.print(new AnnounceDAO().getCount());
System.out.println(new AnnounceDAO().getCount());
%>在这个jsp里,却可以始终与数据库内的记录完全对应。我实在是很费解,struts到底是怎么工作的,会搞成这个样子?有什么解决方法没有?
你提到了过滤器,那么可见action方法addAnnounce()是在一个是事务当中的,你想一下,还能得到吗如果想得到,那么需要设置hibernate的autocommit为true,这样用flush()才能好用,否则就请你提交事务后再来获取count
Transaction tx=null;
try{
//从当前线程中获得session
session=HibernateUtil.getThreadLocalSession();
//开启事务
tx=session.beginTransaction();
//执行请求方法
chain.doFilter(request,response);
//提交事务
tx.commit();
}catch(Exception e){
//捕获到错误回滚事务
if(tx!=null)
tx.rollback();
throw new RuntimeException(e.getMessage(),e);
}finally{
//关闭session
HibernateUtil.closeSession();
}过滤器是这样子的。确实是在提交之前取得count。
但是即使是这样,第二次再访问这个方法,是否也应该是获取前一次的count。
为什么会一直保持一个值不变呢?
HibernateSessionFactory.getSession()来获取当前线程中的session,如果没有则创建一个session,再把这个session放入threadlocal
这样就不需要再进行HibernateUtil.getSessionFactory().openSession();
if(session.isOpen() && session != null)session.close();
真不知道session关闭之后,事务怎么提交,呵呵回答完毕
而getSessionFactory().openSession()我是想再另外通过sessionFactory创建一个session和线程中session的无关,
请问高人,难道这两方法创建的session仍然是同一个?或者出现什么故障了?
唯独这个action中的,无论添加多少个,打印出的始终是第一次的数据。而这个时候jsp中显示的却可以更新。
就没有什么反应,始终不变。 public String addAnnounce(){
//初始化adminservice对象
AnnounceService as=new AnnounceService();
Announce a=new Announce();
a.setAContent(this.announcecontent);
a.setATitle(this.announcetitle);
a.setAAuthor((String)ActionContext.getContext().getSession().get("admin"));
a.setATime(new Date());
as.save(a);
Session session = HibernateUtil.getSessionFactory().openSession();
int count = ((Long)session.createQuery("select count(*) from Announce").uniqueResult()).intValue();
if(session.isOpen() && session != null)session.close();
System.out.println("打印出来: " + count);
return "addannounce";
}但是如果是这样,把session的获得改为 getThreadLocalSession()则就可以出现更新的数据。 public String addAnnounce(){
//初始化adminservice对象
AnnounceService as=new AnnounceService();
Announce a=new Announce();
a.setAContent(this.announcecontent);
a.setATitle(this.announcetitle);
a.setAAuthor((String)ActionContext.getContext().getSession().get("admin"));
a.setATime(new Date());
as.save(a);
Session session = HibernateUtil.getThreadLocalSession();
int count = ((Long)session.createQuery("select count(*) from Announce").uniqueResult()).intValue();
System.out.println("打印出来: " + count);
return "addannounce";
}
请高人给我讲讲背后的原因,谢谢。
public static Session getThreadLocalSession() throws HibernateException {
Session session = (Session) threadLocal.get(); if (session == null || !session.isOpen()) {
if (sessionFactory == null) {
rebuildSessionFactory();
}
session = (sessionFactory != null) ? sessionFactory.openSession()
: null;
threadLocal.set(session);
} return session;
}