Hello,I am using hibernate-2.1.2 with a web application,Tomcat 5 with JSP2.0 and Servlet 2.4.
My problem is that when I update a object(a User instance here) and close the session,Then find() will get the stale object. For example.I first list the Users.there is a User with name "UserA".then I update the User with name "UserB",I can list the users with name "UserB", and the Database is the correct "UserB".But,after a few minute,I refresh the list,and it get the stale old name "UserA".the strange things is that it becomes "UserB" after another few minutes. and will swap between "UserA" and "UserB".Is that strange?
The focus here I think is that I only close the session when update() and do
NOT close the session when find(). because I thought find() does not modify the object's state,so I let the session live between requests.
Can I use the same session between find()?
====My Solve:
If I close the session for each request,It works correctly.I use a Filer to do it. see the last lines.
Thanks a lot.
====Note:some code omited by sign of //......
====User.java:
Code:
package bean;
import java.util.*;
/**
* @hibernate.class table="user"
*/ public class User extends Persistent{
private String name;
private String passwd;
private String sex;
//......
/**
* @hibernate.property length="60"
*/
public String getName(){
return name;
}
public void setName(String value){
name=value;
}
//......
}
====MySessionFactory.java:
Code:
import net.sf.hibernate.cfg.Configuration;
import net.sf.hibernate.*;
import bean.*;
public class MySessionFactory {
public static ThreadLocal thread =null;
private static SessionFactory sessionFactory;
private static ThreadLocal getThread(){
if(thread==null){
thread =new ThreadLocal(); }
return thread;
}
public static Session currentSession() throws HibernateException {
if (sessionFactory == null) init();
Session s = (Session) getThread().get();
if (s == null) {
s = sessionFactory.openSession();
getThread().set(s);
}
return s;
}
public static void closeSession() throws HibernateException {
Session s = (Session) getThread().get();
getThread().set(null);
if (s != null) {
s.flush();
s.close();
}
}
private static void init() {
Configuration conf = null;
try {
conf = new Configuration()
.addClass( User.class )
//......
;
sessionFactory = conf.buildSessionFactory();
} catch (MappingException e) {
e.printStackTrace();
} catch (HibernateException e) {
e.printStackTrace();
}
}
}
====DAO.java
Code:
import net.sf.hibernate.Session;
import net.sf.hibernate.HibernateException;
import net.sf.hibernate.Transaction;
import net.sf.hibernate.type.Type;
import java.util.*;
public class DAO{
public static DAO dao=new DAO();
public List find(String query){
List l=null;
Session s;
try{
s= MySessionFactory.currentSession();
l=s.find(query);
s.flush();
//NO session.close() here
}catch(HibernateException he){
System.out.println("DAO:find():Hibernate Error");
}
return l;
}
public Object update(Object o) throws HibernateException {
Session s = MySessionFactory.currentSession();
Transaction tx = null;
try{
tx = s.beginTransaction();
s.saveOrUpdate(o);
tx.commit();
}catch(HibernateException he){
if ( tx!=null ){
tx.rollback();
}
throw he;
}finally{
MySessionFactory.closeSession();// session.close() here,removed after
I add the filter MyFilter.
}
return o;
}
public Object add(Object o) throws HibernateException {
//Like update()
//......
}
public void remove(Object o) throws HibernateException {
//Like update()
//......
}
//......
}
====The client JSP related code:
Code:
//......
public static List getUsers(){
return dao.find("from User");
}
public static String modUser(User u,String newName){
u.setName(newName);
//......
try{
dao.update(u);
}catch(HibernateException e){
e.printStackTrace();
return "Hibernate Error";
}
return null;
}
//......
====My Solve:
I use a Filter in the webapps(configed in web.xml) to implement "session-per-request".
I also remove the MySessionFactory.closeSession() in DAO.java when update() and other calls.
It works OK for "
session-per-request"
==== MyFilter.java
Code:
public class MyFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {}
public void destroy() {}
public void doFilter(ServletRequest req, ServletResponse res, FilterChain fc) throws ServletException,IOException {
fc.doFilter(req,res);
// close a Hibernate session after each request
try{
MySessionFactory.closeSession();
}catch(HibernateException e){
System.out.println("EncodingFilter:doFilter():HibernateException");
}
}
}
====Acticle looked:
http://www.hibernate.org/168.html