之前在对项目中Hibernate的缓存性能进行测试时发现的一个问题,不知大家有没有遇到或者是解决办法。
问题是:使用sql query且是多表关联查询,并启用查询缓存时,对关联表修改后,查询缓存未能更新,出现了不正确的查询结果集。
测试场景:
1. 用例:为简单起见,测试中使用了两表关联查询。查询指定角色 (roleCode) 的所有已授权限点 (Perm集合)
2. 库表:
权限点表(sys_perm )字段: permCode, permName, moduleCode,...
角色授权表(sys_role_perm )字段: roleCode, permCode, createTime,...
3. 关联查询
(其实仅判断所授权限点编码集合,用Hibernate 关联抓取,就可以解决,并且二级缓存也能很好的控制此问题;即使用 named sql query进行鉴权,也只需查 sys_role_perm表返回 permCode集合。这里返回 perm 集合, 这里主要是为测试关联查询时的cache query问题而举的一个例子)
<!-- 角色拥有的所有已授权限集合 -->
<sql-query name="system.roleperms">
select * from sys_perm t join sys_role_perm o
on t.perm_code = o.perm_code
where o.role_code = :roleCode
</sql-query>
</class>
3. 预置数据:
角色编码: STESTOR,
权限点:permCode 组织新增: ORG_ADD
在 sys_role_perm 表中为 STESTOR 授予 组织管理新增的权限:
(STESTOR,ORG_ADD,2007-3-27 10:34:32)
4. 测试代码:
执行三次doQueryRolePerms 查询功能,在第二次执行完毕时,删除 (STESTOR,ORG_ADD) 这条授权,观察第三次查询是否重新去数据库取数。
for (int i = 0; i < 3; i++) {
System.out.println(" Execute No. " + i + " ********************");
List perms = (List)perm.doQueryRolePerms("STESTOR");
System.out.println("(" + i +")result size:" + perms.size() );
if(i % 2 == 1)
rolePerm.doRemoveByVO(rolePermVO1); //删除授权:STESTOR, ORG_ADD
}
5. 执行分析:
第1,2次执行,由于有预置授权,因此 result size: 1;
第3次执行查询,由于删除了唯一的授权,那么 result size: 0。
6. 实际结果:
Execute No. 0 ********************
2008-10-06 17:26:26,406 [DEBUG](AbstractBatcher.java,324) - select this.PERMCODE as PERM1_0_, this.MODULECODE as MODULE2_15_0_, this.PERMTYPECODE as PERM3_15_0_, this.PERMNAME as PERM4_15_0_, this.PERMDESC as PERM5_15_0_, this.PORTNO as PORT6_15_0_ from (select t.perm_code as permCode,
t.module_code as moduleCode,
t.perm_name as permName,
t.perm_desc as permDesc,
t.port_no as portNo,
t.perm_type_code as permTypeCode
from sys_perm t join sys_role_perm o
on t.perm_code = o.perm_code
where o.role_code = ? ) this
(No.0)result size:1
Execute No. 1 ********************
(No.1)result size:1
2008-10-06 17:26:26,484 [DEBUG](AbstractBatcher.java,324) - delete from SYS_ROLE_PERM where PERM_CODE=? and ROLE_CODE=?
Execute No. 2 ********************
(No.2)result size:1
Time: 0.422
OK (1 test)
从结果可以看出,第1次,执行了查询;
第2次没有执行查询,说明 query cache,二级cache都起了作用。
但第3次查询,没有重新执行sql,仍然返回的是第二缓存的结果。
因此可以判定, 第3次查出的是旧数据。
7. 分析及结论:
Hibernate query cache 在关联表的数据删除时,没能通知查询缓存及时失效或更新, 以便获取最新数据。
8. 解决办法
暂时还没找到Hibernate自身的解决办法, 为避免此问题,可以关闭查询缓存。 看大家有没有遇到过此问题,分享下你们的经验。
如果hibernate真的没有解决这个问题,我能想到的一个思路就是,在 named query执行时,分析出查询的关联表,并在关联表进行 create,update,delete时及时通知该 named query的缓存失效。
关联查询,特别是多表关联,且操作复杂时,要精细的进行缓存通知比较困难(例如:修改了 Admin 角色的授权,就对上例的查询没有影响,而修改了 STESTOR 角色的授权才需要通知cache更新,但这判断起来有一定难度),可以做一个笼统的逻辑,即 create,update,delete 关联表后,对 named query的cache都要通知它清除,以便重新查询获取最新数据。
query cache的利用率,即命中率取决于具体业务的增删改操作的频率,这个测试暂不考虑此因素 query cache的价值问题。
经过一天的努力,终于解决此问题, 并附源代码和fix包:
解决Hibernate SQL Query Cache的一个可靠性问题(附源码)
分享到:
相关推荐
### Hibernate事务缓存知识点详解 #### 一、Hibernate框架简介 ...通过学习这些内容,可以帮助开发者更好地理解Hibernate框架的核心特性,并在实际项目中更有效地利用这些功能来提升应用程序的性能和可靠性。
### Hibernate缓存管理详解 #### 一、缓存概述 **缓存(Cache)**是在计算机领域中广泛应用的一种技术手段,其主要目的是提高应用程序的运行效率。缓存位于应用程序与永久性数据存储(例如硬盘上的文件或数据库)...
Hibernate 是一个开源的、强大的 ORM 解决方案,它允许开发者用 Java 对象来操作数据库,从而简化了数据库编程,提高了开发效率。 这份文档分为多个章节,深入讲解了 Hibernate 的核心概念、配置、实体映射、查询...
总之,将Memcached集成到Hibernate作为二级缓存,能够显著提升系统性能,但同时也需要合理配置和管理,以确保系统的可靠性和数据的一致性。通过上述jar包,开发者可以轻松地将这两者结合,为Java应用带来更高的效率...
这些改进进一步提升了Hibernate的灵活性和可靠性。 3. Hibernate核心组件: - Configuration:配置对象,负责加载hibernate.cfg.xml配置文件,初始化SessionFactory。 - SessionFactory:会话工厂,是线程安全的...
在3.1.x版本中,对事务处理的异常处理和回滚逻辑进行了细化,提高了系统的稳定性和可靠性。 七、方言支持 Hibernate支持多种数据库,通过方言(Dialect)来适应不同的SQL语法。3.1.x版本中,Hibernate已经包含了对...
在Java世界中,Hibernate是一个非常流行的ORM(对象关系映射)框架,它允许开发者用面向对象的方式处理...然而,使用缓存的同时也要注意缓存管理和维护,避免出现缓存雪崩、缓存穿透等问题,确保系统的稳定性和可靠性。
总的来说,Hibernate 5.3.0是一个强大且成熟的ORM框架,它的特性包括但不限于:强大的对象关系映射、高效的查询机制、完善的缓存策略、对Java 8的完美支持以及丰富的扩展性。通过下载并使用这个jar包,开发者能够...
Hibernate 3.2 版本是 Hibernate 系列的一个重要里程碑,引入了许多改进和新特性,以提高性能和易用性。以下是对 Hibernate-3.2 源码包中的关键知识点的详细解释。 1. **对象关系映射(ORM)**:ORM 是 Hibernate ...
6. **集成测试与部署**:指导如何在开发周期的不同阶段进行集成测试,确保系统的稳定性和可靠性。 #### 四、关键技术知识点详解 1. **对象关系映射(ORM)原理** - ORM是一种编程技术,用于将对象模型与关系型...
首先,Hibernate 4.1.4是Hibernate框架的一个稳定版本,它包含了众多的性能优化和新特性。此版本的主要改进在于对JPA 2.1规范的支持,这意味着开发者可以利用更多的标准API来处理数据,提高了代码的可移植性。此外,...
在Hibernate开发中,使用JUnit进行单元测试是非常常见的,可以确保代码的正确性和持久层操作的可靠性。 4. 其他可能包含的库: - `hibernate-entitymanager.jar`:提供了JPA(Java Persistence API)的实现,使得...
描述中提到的"官网下的jar包"意味着这些文件直接来源于Hibernate的官方网站,确保了文件的权威性和可靠性。"其中的lib中jar包打包下载"意味着这个压缩包包含了Hibernate库中所有的依赖JAR文件,这些文件通常位于项目...
Hibernate 是一个开源的对象关系映射(ORM)框架,它为 Java 开发者提供了一种在 Java 应用程序中管理关系数据库的方式。通过 ORM,Hibernate 可以将 Java 类与数据库表之间的映射关系自动化,从而简化数据访问层的...
6. **Hibernate缓存机制的负面问题** - 虽然缓存能提高效率,但如果不妥善管理,可能导致数据一致性问题,如并发环境下缓存的数据未及时同步到数据库,或者缓存中的过期数据被读取。 7. **hibernate cache 缓存** ...
Hibernate 5.3.0.Final是该框架的一个稳定版本,包含了以下关键功能: 1. **实体管理**:Hibernate通过将Java类与数据库表进行映射,使得我们可以直接对Java对象进行操作,而无需关心底层的SQL语句。 2. **会话接口...
- **bug 修复**:修复了之前版本存在的问题,确保软件的稳定性和可靠性。 - **API 稳定性**:随着 Hibernate 的成熟,其 API 会变得更加稳定,减少了不必要的变更,方便开发者长期使用和维护。 在实际使用 ...
在Java世界中,Hibernate是一个强大的对象关系映射(ORM)框架,它简化了数据库操作,使得开发者可以使用面向对象的方式来处理数据。这篇关于“hibernate测试”的文章旨在深入探讨Hibernate的核心概念,以及如何进行...