【发布时间】: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