Hibernate的二级缓存,主要针对使用标识符属性进行查询的缓存策略。Hibernate还专门用于条件查询的查询缓存(Query Cache)。使用查询缓存功能,需要让两次查询所对应的HQL语句相同,同时这两次查询之间表中的数据没有任何变动。

1、Hibernate查询缓存的实现原理

查询缓存使用Map对象保存被缓存的对象,该对象的Key值根据HQL所生成的SQL语句、查询的参数及分页参数等构造,保证同样查询下有相同的Key值。如果该HQL查询返回一个List对象,Key值对应的Value值为List中个各个元素的标识符属性值(id)的集合;如果HQL查询中包含select子句,则为所有查询到的数据。

应用查询缓存使用HQL语句查询时会根据当前查询所使用的Key值在缓存中查找所对应的缓存数据,如果存在,则返回该HQL语句所对应的缓存数据;否则查询数据库获取数据并将其对应的Key值组合后保存到缓存的Map对象中。

如果缓存数据对应的表和数据发生修改、删除及添加等操作,则清空缓存区。底层实现上Hibernate记录每个缓存最后更新时间,并且每个查询缓存都有一个生成时间。Hibernate使用一个查询缓存时会比较这个缓存数据对应的表的最后更新时间和这个缓存的生成时间,如果前者大于后者,则这个缓存无效。

2、缓存对get()、load()、list()和iterator()方法的影响

在Hibernate中查询获取数据库表中数据的方式有多种,既可以使用Session对象的get()方法,又可以使用Query和Criteria对象的list()和iterator()方法。这几个方法在使用方法上接近,但是在某个情况下,特别在这些方法结合缓存后查询性能的差异比较大。

(1)、Session对象的load()方法

 Hibernate在执行该方法时首先从当前一级缓存中查询当前标识符属性(id)对应的数据,如果未命中,则判断该持久化对象是否配置了二级缓存。如果配置了,则从二级缓存中查询标识符属性对应的数据;否则从数据库中查询数据并缓存到对应的一级和二级缓存中。

(2)、Session对象的get()方法

 Hibernate在执行该方法时首先从当前一级缓存中查询当前标识符属性(id)对应的数据,如果未命中缓存,则直接从数据库中查询数据并缓存到相应的一级缓存中。

(3)、Query对象的list()方法

 Hibernate在执行Query对象的list()方法首先检查是否配置了查询缓存,如果配置,则判断是否能命中缓存。如果未命中,则直接从数据库中查询数据并缓存到相应的一级、二级和查询缓存中。如果Query对象的list()方法从查询缓存中获取的是标识符属性值的集合,则需要根据标识符属性值获取所相应的数据。

(4)、Query对象的iterator()方法

 Hibernate在执行Query对象的iterator()方法时首先在数据库中查询所有符合查询条件的标识符的属性值,即执行select id from +对象这样的SQL语句,然后通过Session对象的load()方法查询当前标识符对应的数据。