【问题标题】:Hibernate two sessions data unsynchronize休眠两个会话数据不同步
【发布时间】:2020-12-12 07:46:15
【问题描述】:

我有一个使用 Tomcat、hibernate 和 GWT 框架的 Web 应用程序,数据库是 MySQL。

在数据库中,有一个表名“menu”,该表中的三列是:

id(INT自增,PK),
名称 (VARCHAR(45)),
启用 (TINYINT(1))。

我在hibernate中定义了一个POJO类名Menu,如下:

public class Menu implements Serializable{
    private static final long serialVersionUID = -6374314909068269446L;

    private int id;
    private String name;
    private boolean enable = true;

    ***getters and setters***

    @Override
    public int hashCode(){
        final int prime = 31;
        int result = 1;
        result = prime * result + id;
        return result;
    }

    @Override
    public boolean equals(Object obj){
        if(this == obj)
            return true;
        if(obj == null)
            return false;
        if(getClass() != obj.getClass())
            return false;
        Menu other = (Menu) obj;
        if(id != other.id)
            return false;
        return true;
    }
}

hibernate 的 Menu.hbm.xml 中的内容如下:

<hibernate-mapping>
    <class name="com.yabtogo.tth.server.pojo.Menu" table="menu" >
        <id name="id" type="int">
            <column name="id" not-null="true"/>
            <generator class="native" />
        </id>
        
        <property name="name" type="string">
            <column name="name" length="45" />
        </property>
        
        <property name="enable" type="boolean">
            <column name="enable" not-null="true"/>
        </property>
        
    </class>
</hibernate-mapping>

hibernate 配置文件非常简洁,如下所示:

<hibernate-configuration>
    <session-factory>
        <property name="show_sql">true</property>   
        <property name="format_sql">true</property> 
        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
        <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="connection.url">jdbc:mysql://127.0.0.1:3306/teatimehelper</property>
        
        <property name="connection.username">root</property>
        <property name="connection.password">123456</property>
        
        <property name="javax.persistence.validation.mode">auto</property>

        <property name="hibernate.connection.CharSet">utf8</property>
        <property name="hibernate.connection.characterEncoding">utf8</property>
        <property name="hibernate.connection.useUnicode">true</property>

        <mapping resource="com/yabtogo/tth/server/pojo/SystemLog.hbm.xml" />
        <mapping resource="com/yabtogo/tth/server/pojo/Menu.hbm.xml" />
        
    </session-factory>
</hibernate-configuration>

我在Tomcat中通过servlet编辑表格菜单的数据,大致是这样的:

Menu menu = null;
Session session = null;
try{
   session = DBHelper.getInstance().getSession();
   Query query = session.createQuery("from Menu where name = :name");
   query.setString("name", name);
   menu = (Menu) query.uniqueResult();
   if(menu == null){
      DBHelper.closeSession(session);
      return;
   }
        
}catch(Exception e){
   e.printStackTrace();
   DBHelper.closeSession(session);
   return;        
}

*** do some other operations ***

Transaction transaction = null;
        
try{
   menu.setEnable(false);
   SystemLog log = new SystemLog(clientIP, clientHost, name); //another pojo
   transaction = session.beginTransaction();
   session.update(menu);
   session.save(log);
   transaction.commit();
   DBHelper.closeSession(session);
   return;
   
}catch(Exception e){
   e.printStackTrace();
   try{
      if(transaction != null){
         transaction.rollback();
      }
               
   }catch(Exception rollbackException){
      rollbackException.printStackTrace();
   }
   DBHelper.closeSession(session);
   return; 
}

DBHelper 类如下:

public class DBHelper{
    private static DBHelper instance = null;
    public static DBHelper getInstance(){
        if(instance == null){
            instance = new DBHelper();
        }
        return instance;
    }
    
    private Configuration config = null;
    private SessionFactory sessionFactory = null;
    
    private DBHelper(){
        config = new Configuration().configure("hibernate.cfg.xml");
        sessionFactory = config.buildSessionFactory();
    }
    
    public Session getSession(){
        Session session = sessionFactory.openSession();
        return session;
    }

    public static void closeSession(Session session){
        if(session == null){
            return;
        }
        if(!session.isOpen()){
            return;
        }
        try{
            session.close();
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

我使用 GWT 框架并定义了一个 RPC 服务。在那个 PRC 服务实现类中,我像这样加载菜单的数据:

public class MenuServiceImpl extends RemoteServiceServlet implements MenuService{

    private static final long serialVersionUID = -710770410849236369L;

    @Override
    public List<Menu> getMenu(){
        Session session = DBHelper.getInstance().getSession();
        List<Menu> menus = null;
        try{
            String hql = "from Menu where enable = true order by id desc";
            Query query = session.createQuery(hql);
            menus = query.list(); 
            return menus;
        }catch(Exception e){
            e.printStackTrace();
            return null;
        }finally{
            DBHelper.closeSession(session);
        }
    }
}

但是通过这个Query取回数据后,我在上层servlet中编辑的数据仍然取回,哪些数据我已经将启用列更改为“false”,并且在数据库中已经更改,但它仍然被读回MenuServiceImpl 的 getMenu() 方法,POJO 实例的 enable 属性为“true”,怎么会?我不知道为什么? 并非所有编辑的数据都会被读回,但这种情况经常发生。

我使用 sessionFactory.openSession() 来获取一个新的 Session 实例,所以它应该没有任何 session 的缓存数据,而且我没有使用 SessionFactory 的缓存更不用说数据已经写入数据库了。 那为什么RPC服务实现类MenuServiceImpl还是会读回旧数据呢?

【问题讨论】:

    标签: hibernate


    【解决方案1】:

    问题解决了。 Hibernate会话的数据不同步,因为我使用的是Hibernate内置的连接池算法,比较简陋,在hibernate的文档中,它说它只是为了帮助我们入门,并不打算在生产系统中使用。 在我改用 C3P0 后,一切正常。 我在 hibernate.cfg.xml 中添加了这些属性:

    <property name = "hibernate.c3p0.min_size">1</property>
    <property name = "hibernate.c3p0.max_size">5</property>
    <property name = "hibernate.c3p0.timeout">0</property>
    <property name = "hibernate.c3p0.max_statements">50</property>
    

    【讨论】:

      猜你喜欢
      • 2012-02-10
      • 1970-01-01
      • 2018-11-30
      • 2011-01-17
      • 2012-06-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多