映射文件的详细配置请参考配套光盘中的hibernate\\src\\cn\\hxex\\cache\\User.hbm.xml文件。 测试主程序
在这里的测试主程序采用了多线程的运行方式,以模拟在不同Session的情况下是否真的可以避免查询的重复进行。
在这个测试程序中,所做的工作就是依据ID来得到对应的实体对象,并将其输出。然后通过多次运行此程序,来检查后面的运行是否进行了数据库的操作。 测试主程序的主要测试方法的实现如清单14.10所示。 清单14.10 测试主程序的实现 ……
public void run() {
SessionFactory sf = CacheMain.getSessionFactory();
Session session = sf.getCurrentSession();
session.beginTransaction();
User user = (User)session.get( User.class, \"1\" ); System.out.println( user );
session.getTransaction().commit(); }
public static void main(String[] args) {
CacheMain main1 = new CacheMain(); main1.start();
CacheMain main2 = new CacheMain(); main2.start(); } }
运行测试程序
在运行测试程序之前,需要先手动地向数据库中增加一条记录。该记录的ID值为1,可以采用下面的SQL语句。
INSERT INTO userinfo(userId, name, age) VALUES( '1', 'galaxy', 32 ); 接下来在运行测试主程序时,应该看到类似下面的输出:
Hibernate: select user0_.userId as userId0_0_, user0_.name as name0_0_, user0_.age as age0_0_ from USERINFO user0_ where user0_.userId=? ID: 1
Namge: galaxy Age: 32 ID: 1
Namge: galaxy Age: 32
通过上面的结果可以看到,每个运行的进程都输出了User对象的信息,但在运行中只进行了一次数据库读取操作,这说明第二次User对象的获得是从缓存中抓取的,而没有进行数据库的查询操作。 14.2.3.7 查询缓存
查询缓存是专门针对各种查询操作进行缓存。查询缓存会在整个SessionFactory的生命周期中起作用,存储的方式也是采用key-value的形式来进行存储的。
查询缓存中的key是根据查询的语句、查询的条件、查询的参数和查询的页数等信息组成的。而数据的存储则会使用两种方式,使用SELECT语句只查询实体对象的某些列或者某些实体对象列的组合时,会直接缓存整个结果集。而对于查询结果为某个实体对象集合的情况则只会缓存实体对象的ID值,以达到缓存空间可以共用,节省空间的目的。 在使用查询缓存时,除了需要设置hibernate.cache.provider_class参数来启动
二级缓存外,还需要通过hibernate.cache.use_query_cache参数来启动对查询缓存的支持。
另外需要注意的是,查询缓存是在执行查询语句的时候指定缓存的方式以及是否需要对查询的结果进行缓存。
下面就来了解一下查询缓存的使用方法及作用。 修改Hibernate配置文件
首先需要修改Hibernate的配置文件,增加hibernate.cache.use_query_cache参数的配置。配置方法如下:
true
Hibernate配置文件的详细内容请参考配套光盘中的hibernate\\src\\cn\\hxex\\ hibernate\\cache\\hibernate.cfg.xml文件。 编写主测试程序
由于这是在前面二级缓存例子的基础上来开发的,所以,对于EHCache的配置以及视图对象的开发和映射文件的配置工作就都不需要再重新进行了。下面就来看一下主测试程序的实现方法,如清单14.11所示。 清单14.11 主程序的实现 ……
public void run() {
SessionFactory sf = QueryCacheMain.getSessionFactory(); Session session = sf.getCurrentSession();
session.beginTransaction();
Query query = session.createQuery( \"from User\" ); Iterator it = query.setCacheable( true ).list().iterator(); while( it.hasNext() ) {
System.out.println( it.next() ); }
User user = (User)session.get( User.class, \"1\" ); System.out.println( user );
session.getTransaction().commit(); }
public static void main(String[] args) {
QueryCacheMain main1 = new QueryCacheMain(); main1.start(); try {
Thread.sleep( 2000 );
} catch (InterruptedException e) { e.printStackTrace();
}
QueryCacheMain main2 = new QueryCacheMain(); main2.start(); } }
主程序在实现的时候采用了多线程的方式来运行。首先将“from User”查询结果进行缓存,然后再通过ID取得对象来检查是否对对象进行了缓存。另外,多个线程的执行可以看出对于进行了缓存的查询是不会执行第二次的。 运行测试主程序
接着就来运行测试主程序,其输出结果应该如下所示:
Hibernate: select user0_.userId as userId0_, user0_.name as name0_, user0_.age as age0_ from USERINFO user0_ ID: 1
Namge: galaxy Age: 32 ID: 1
Namge: galaxy Age: 32 ID: 1
Namge: galaxy Age: 32 ID: 1
Namge: galaxy Age: 32
通过上面的执行结果可以看到,在两个线程执行中,只执行了一个SQL查询语句。这是因为根据ID所要获取的对象在前面的查询中已经得到了,并进行了缓存,所以没有再次执行查询语句。