最近一段时间做项目的时候,自已在修改一个功能点,要更改已获取的数据列表中的某行记录内容,并将更改保存到数据库中,已写好了所有业务代码,在调用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所代码管理的会话对象。
分享到:
相关推荐
7. **会话(Session)**: Hibernate的核心接口,用于执行CRUD操作。 8. **事务(Transaction)**: 确保数据的一致性,通过SessionFactory创建并管理。 **三、Hibernate工作流程** 1. **初始化SessionFactory**: ...
- **Session**:是数据库会话,提供了与数据库交互的一系列方法,如增删查改等操作。 - **Query/Criteria API**:提供SQL查询的替代方案,支持动态和静态查询,使得代码更具有可读性和可维护性。 - **Transaction**...
了解如何优化Hibernate,包括批处理、合理使用缓存、避免N+1查询问题、减少无效的数据库访问等策略。 通过阅读压缩包中的`Hibernate原理与配置快速入门.pdf`和`Hibernate_DEV_GUIDE.pdf`,你可以深入了解Hibernate...
Hibernate是一款开源的对象关系映射(ORM)框架,它允许Java开发者在关系数据库和对象模型之间建立桥梁,使得数据库操作可以通过对象的方式进行,极大地简化了Java应用程序的开发。本中文帮助文档详细介绍了...
3. Session:作为数据库会话的代理,Session负责管理对象的状态并执行数据库操作。 4. Transaction:事务处理确保了数据的一致性,Hibernate支持JTA和JDBC事务。 5. Criteria查询和HQL:Hibernate提供了面向对象的...
在Hibernate中,`Session`是数据库会话的抽象,负责对象的持久化操作。而`Transaction`则用于管理数据库事务,确保数据的一致性。通过SessionFactory创建Session,然后在Transaction中执行CRUD操作。 五、对象持久...
会话(Session)是与数据库交互的桥梁,负责执行SQL语句、管理事务。会话的生命周期包括打开、关闭、持久化、加载和更新实体等操作。 5. **查询语言HQL与Criteria API** Hibernate提供了两种查询方式:HQL...
Session是数据库会话,处理CRUD操作;Query则用于执行SQL查询。 二、优化配置 1. 第二级缓存:启用和配置第二级缓存,如使用Ehcache或Infinispan,能有效减少对数据库的访问。 2. 异步初始化:通过设置hibernate....
- **打开Session**:`Session`对象代表了和数据库的一次会话,它是非线程安全的,每个线程都应该有自己的`Session`实例。 - **创建事务Transaction**:在进行数据库操作之前,通常需要开启一个事务。 - **持久化操作...
创建(Create)、读取(Read)、更新(Update)、删除(Delete)是数据库操作的基本动作。使用NHibernate,可以通过会话的Save、Load、Update、Delete方法来实现这些操作。例如,保存新对象使用`session.Save(object...
3. **会话管理**:NHibernate提供Session接口来管理数据库会话,它是数据库操作的主要入口点。Session负责缓存管理、事务控制以及对象的持久化和检索。 4. **查询语言**:NHibernate支持HQL(Hibernate Query ...
解决方法是确保在Session关闭前完成懒加载操作,或考虑使用Eager Loading或Open Session In View模式。 理解并有效地处理这些异常对于Java开发者来说至关重要,它们能帮助我们诊断并修复问题,保证应用程序的稳定性...
4. Session和Transaction管理:在业务逻辑层中,通过SessionFactory获取Session对象,Session是与数据库会话的入口点。对数据库的所有操作都在Transaction中进行,以确保数据一致性。 5. CRUD操作:使用Session的...
7. **错误处理与响应**:当用户输入无效或者数据库操作失败时,Servlet需要正确处理异常,并向用户返回适当的错误信息。这可以是HTTP状态码,也可以是自定义的错误页面。 8. **会话管理**:如果用户成功登录,你...
UserSessionAction.java可能包含用于创建、更新和销毁会话的函数,例如`startSession()`, `updateSession()`, `endSession()`。会话中可能存储关键信息,如用户的ID,以标识已认证的用户。 3. **状态跟踪**:为了...
- 设置会话超时,以防用户长时间未操作导致购物车数据无效。 4. 商品实体类(Goods Entity): - 定义一个包含商品ID、名称、价格和数量等属性的Java类,用于存储购物车中的商品信息。 5. 数据库操作: - 存储...
在使用Java JDBC与Oracle数据库进行交互时,有时可能会遇到执行`executeUpdate`方法时程序卡死的问题。这通常是由于事务管理不当导致的,特别是当数据库事务未被正确提交或回滚时。下面我们将深入探讨这个问题的原因...
4. **会话管理**:成功登录后,服务器通常会创建一个session(会话)来跟踪用户状态。这可以通过HttpSession接口实现,存储用户信息,以便在用户浏览不同页面时识别他们。 5. **数据库操作**:注册时,用户信息会被...
同时,为了防止会话劫持,应定期更新session ID。 以上就是使用Struts框架实现用户注册与登录功能的基本步骤。这个过程涉及到了前端交互、后端处理、数据库操作以及安全策略等多个方面,每个环节都需要细心处理以...