最近一段时间做项目的时候,自已在修改一个功能点,要更改已获取的数据列表中的某行记录内容,并将更改保存到数据库中,已写好了所有业务代码,在调用DAO层Hibernate方法执行数据库更新时,发现一个有意思的问题,程序执行数据库更新操作无任何异常,但是在刷新列表时,却发现该行数据根本没有更改。
经过分析与查找,确认是hibernate缓存问题,导制数据库操作无法真正的执行。具体原因是如何导制的,我没有正确答案,但可以肯定跟缓存有关。
具体代码如下:
/**
* 修改指定流程下的节点内容
* @param lcbh
* @param lcmc
* @param oldJdbh
* @param oldJdmc
* @param newJdbh
* @param newJdmc
* @return
* @throws Exception
*/
public boolean updateLcjdDb(String lcbh,String lcmc,String oldJdbh,String oldJdmc,String newJdbh,String newJdmc) throws Exception {
Session session = this.getSession();
Transaction tx =null;
String hql="update BFsYwbd set jdph=?,jdmc=? where lcph=? and lcmc=? and jdph=? and jdmc=?";
int count=0;
try{
tx = session.beginTransaction();
Query query=this.getSession().createQuery(hql);
query.setString(0, newJdbh);
query.setString(1, newJdmc);
query.setString(2, lcbh);
query.setString(3, lcmc);
query.setString(4, oldJdbh);
query.setString(5, oldJdmc);
count=query.executeUpdate();
tx.commit();
session.flush();
}catch(Exception e){
tx.rollback();
throw e;
}
return count>=1?true:false;
}
上面一段代码从运行角度来看无任何问题,但是就是无法将更新操作应用到数据库层面。
推测,可能是在执行数据库操作时由hibernate获取了缓存中的已有的数据列表,并对该列表中的指定对象进行了操作,但没有将该对象的操作执行到数据库中(注:所查询出的列表是经过数据库去掉重复项之后的集合,可能hibernate对缓存中的数据列表行进行了更新之后,却无法将该更改后的列表行缓存对象匹配到数据库中指定的记录行,导制无法真实的修改数据库中的记录,因为缓存中的对象已在数据库中找不到记录行或唯一行),hibernate的缓存策略是每个对应数据库表的缓存记录都具有会话ID,它保存了数据库中的记录与缓存中的对象一致,一但缓存中的记录发生更新操作,hibernate就会通过缓存机制找到对应数据库中表的数据,将其更改。代码中的是通过getSession()获取Session对象,在通过开启事务进行更新操作,最后提交事务,刷新缓存。 我们了解到通过getSession()所获取的Session对象,都是重新创建的一个新的会话对象,而我的功能中所获取的数据列表是通过getHibernateTemplate().find()执行得到的。getHibernateTemplate()方法是由spring通过在控制反转代理管理数据库连接sessionFactory所得到的,也就是说getHibernateTemplate方法中得到的会话对象是从sessionFactory会话工厂中得到,而sessionFactory会话工厂中会保持一个有用的Session会话,而不是每次通过调用getHibernateTemplate()方法都会创建的,这与getSession()正好相反。因此推测到,在通过getSession()所生成的会话对象更改数据库时,会从hibernate的所有缓存中找到数据列表,但该会话对象只对该数据列表中的数据进行更新之后,并提交了事务刷新了会话对象,实际上就是清空了该Session会话,而该操作之对当前从getSession()中所获取会话缓存数据有效,实际上并没有更新Spring控制反转代理数据库连接所产生的sessionFactory会话工厂中的缓存数据。其最后结果就是更新了getSession()方法生成的会话对象中的数据缓存,而getSession()所产生的Session会话对象不被Spring所代理管理,而是将一个原始的最新的会话,就导制了原有的通过getHibernateTemplate()所生成的Spring代理的sessionFactory会话工厂的数据表列记录不能修改,sessionFactory会话工厂中所缓存的数据列表记录不能修改,其对应的数据库表记录也就不会有更新操作。
经过以上推测和分析之后,就大致明白了些。不过只是个人的见解,不一定是正确的方向。
经过修改后的代码如下:
/**
* 修改指定流程下的节点内容
* @param lcbh
* @param lcmc
* @param oldJdbh
* @param oldJdmc
* @param newJdbh
* @param newJdmc
* @return
* @throws Exception
*/
public boolean updateLcjdDb(String lcbh,String lcmc,String oldJdbh,String oldJdmc,String newJdbh,String newJdmc) throws Exception {
Session session = this.getHibernateTemplate().getSessionFactory().openSession();
Transaction tx =null;
String hql="update BFsYwbd set jdph=?,jdmc=? where lcph=? and lcmc=? and jdph=? and jdmc=?";
int count=0;
try{
tx = session.beginTransaction();
Query query=this.getSession().createQuery(hql);
query.setString(0, newJdbh);
query.setString(1, newJdmc);
query.setString(2, lcbh);
query.setString(3, lcmc);
query.setString(4, oldJdbh);
query.setString(5, oldJdmc);
count=query.executeUpdate();
tx.commit();
session.flush();
}catch(Exception e){
tx.rollback();
throw e;
}
return count>=1?true:false;
}
从上面的代码中可以看出,其实就是将getSession()方法获取Session会话对象,改为通过this.getHibernateTemplate().getSessionFactory().openSession()获取Spring所代码管理的会话对象。
分享到:
相关推荐
使用Hibernate的Session对象操作数据库 1.初始化Hibernate:在要使用Hibernate的类的方法中实例化Configuration对象并用Configuration对象的configure()方法将hibernate.cfg.xml中的配置加载到内存,即: ...
session驱动类 session存入数据库 数据库存储session 用于session存入数据库
重写session机制,默认session是以临时文件形式存储在服务器,将session写入数据库,建表和注释写的都很清晰,已测试
Hibernate Session释放模式
hibernate配置文件,session工厂学习,session链接数据库
NULL 博文链接:https://shaozhen.iteye.com/blog/946680
session 存入数据库session 存入数据库session 存入数据库session 存入数据库
web项目开发过程中经常遇到用户登陆,退出的问题,根据登陆和退出来操作session的存值和销毁. 但往往很多用户不去点击"退出",而是关闭FF的tab或浏览器(多种浏览器),这就给session的销毁带来了困难.
Hibernate-nosession浅谈代码案例。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
本书详细阐述了php中的session会话固定漏洞可能引发的安全问题,叙述了php代码审计的一些tips。
hibernate中session的管理描述。 hibernate中session的管理描述。
session会话管理,session的原理,API,应用案例
基于Session会话的网站推荐系统研究.nh 基于Session会话的网站推荐系统研究.nh
session.js, Session.js 获取用户会话信息 Session.js提供有关当前会话的信息。要使用:包括文件 session.js, 然后访问访问者对象。 它使用google加载器获取位置数据。 对于异步加载,请使用 window.session_loaded ...
在spring+hibernate的框架中定时操作数据库,主要是拿到sessionFactory,不会出现no session 和transaction no-bound等问题,由sessionFactory完成对数据的操作,有些包是没有用的,有兴趣的可以自己删除掉
Hibernate 中对session的管理!
在ORACLE数据库杀掉会话进程有三种方式: 1:ALTER SYSTEM KILL SESSION 关于KILL SESSION Clause ,官方文档描述alter system kill session实际上不是真正的杀死会话,它只是将会话标记为终止。等待PMON进程来清除...
Hibernate 与数据库中的触发器协同工作时, 会造成两类问题 1、触发器使 Session 的缓存中的持久化对象与数据库中对应的数据不一致:触发器运行在数据库中, 它执行的操作对 Session 是透明的 Session 的 解决...
insert方法 代码如下:public void insert(Object o){Session session = HibernateSessionFactory.currentSession();Transaction t = session.beginTransaction();session.save(o);t.commit();Hibernate...