休眠两个会话数据不同步



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

在数据库中,有一个表名";菜单";该表中的三列是:

id(INT自动递增,PK(,
name(VARCHAR(45((,
enable(TINYINT(1((。

我在hibernate中定义了一个POJO类名菜单,如下所示:

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.ibm.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服务实现类中,我加载Menu的数据,如下所示:

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);
}
}
}

但是通过这个查询返回数据后,我在上层servlet中编辑的数据仍然会返回,我已经将enable列更改为";"假";,并且它已经在Database中发生了变化,但它仍然在MenuServiceImpl的getMenu((方法中被读取,并且它POJO实例的enable属性是";真";,怎么会这样?我不知道为什么?并不是每一个编辑过的数据都会被读回,但这种情况经常发生。

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

问题已解决。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>

最新更新