本文介绍EhCache查询缓存中数据,EhCache提供了类似Hibernate的查询API,可以按照给定的条件进行查询。
要对EhCache进行查询,需要在ehcache.xml中设定要查询的属性
数据准备
@Before
public void setUp() {
//加载EhCache配置文件
InputStream in = EhcacheTest.class.getClassLoader().getResourceAsStream("ehcache-query.xml");
CacheManager cm = CacheManager.create(in);
cache = cm.getCache("data-query");
Person p1 = new Person(1, "Tom", 34);
Person p2 = new Person(2, "Tom", 34);
Person p3 = new Person(3, "Jack", 32);
Person p4 = new Person(4, "Jack", 32);
//添加三个元素,Key是Person对象的ID
Element element = new Element(p1.getId(), p1);
cache.putIfAbsent(element);
element = new Element(p2.getId(), p2);
cache.putIfAbsent(element);
element = new Element(p3.getId(), p3);
cache.putIfAbsent(element);
//添加一个元素,Key和Value都是Person对象
cache.putIfAbsent(new Element(p4, p4));
}
1. 在上面的测试setup方法中,为缓存添加了四个元素。前三个以person的id作为key,最后一个以person对象本身作为key 2.四个person对象,有些数据是相同的,方便后面按照Value的指定属性进行查询
基本查询
对EhCache最基本的需求是对缓存元素的Key和Value进行查询,这在ehcache.xml中需要做如下配置
<cache>
<searchable/>
</cache>
searchable有两个可选属性,keys和values,它们的默认值都是true,即默认情况下,EhCache已经将Key和Value的查询添加上了,查询属性分别是key和value。上面的设置等价于
<cache>
<searchable keys="true" values="true"/>
</cache>
如果不允许针对keys或者values进行查询,将它置为false即可。
测试一:查询所有数据
//查询缓存中所有的数据
@org.junit.Test
public void test0() {
Query query = cache.createQuery();
Results results = query.includeKeys().includeValues().execute();
List<Result> resultList = results.all();
Assert.assertEquals(4, resultList.size());
}
测试二: 根据Key(简单类型查询)进行条件查询
//根据简单查询属性类型(Key是整型)进行查询
@org.junit.Test
public void test1() {
Query query = cache.createQuery();
query.includeKeys(); //查询结果中包含Key
query.includeValues(); //查询结果中包含Value
Attribute<Integer> attribute = cache.getSearchAttribute("key"); //按照EhCache内置的可查询属性key进行查询
query.addCriteria(attribute.eq(2)); //查询条件:key为2,2是简单类型
Results results = query.execute();
List<Result> resultList = results.all();
Result result = resultList.get(0);
Integer key = (Integer) result.getKey();
org.junit.Assert.assertEquals(2, key.intValue());
Person value = (Person) result.getValue();
Assert.assertEquals(value.getAge(), 34);
}
测试三: 根据Key(复杂类型查询)进行条件查询
样例数据中,第四个元素的key和value都是Person对象,如何创建把它查询出来?
@org.junit.Test
public void test2() {
Query query = cache.createQuery();
query.includeKeys();
query.includeValues();
Attribute<Person> attribute = cache.getSearchAttribute("key");
Person p4 = new Person(4, "Jack", 32);
query.addCriteria(attribute.eq(p4));
Results results = query.execute();
List<Result> resultList = results.all();
Assert.assertNotNull(resultList);
Assert.assertEquals(resultList.size() , 1);
}
这个查询会抛出如下异常,表明,Person是一个不支持的查询类型,至于为什么会抛出这个异常,在后面讲到
net.sf.ehcache.search.SearchException: Unsupported type for search attribute [key]: com.tom.Person
at net.sf.ehcache.search.attribute.AttributeType.typeFor(AttributeType.java:236)
at net.sf.ehcache.search.expression.EqualTo.<init>(EqualTo.java:54)
at net.sf.ehcache.search.Attribute.eq(Attribute.java:161)
查询结果排序
对查询的结果进行排序,也是常见的需求,下面是一个查询结果倒排序的例子:
测试四: 查询结果排序
@org.junit.Test
public void test3() {
Query query = cache.createQuery();
Attribute<Integer> attribute = cache.getSearchAttribute("key");
//降序
Results results = query.includeKeys().includeValues().addOrderBy(attribute, Direction.DESCENDING).execute();
List<Result> resultList = results.all();
org.junit.Assert.assertEquals(4, resultList.size());
Result result = resultList.get(0);
Object key = result.getKey();
Object value = result.getValue();
Assert.assertTrue(value instanceof Person);
Person person = (Person) value;
//排序结果,id为3的Person对象最大
}
这里按照Key进行倒排序查询,查看结果,可知,结果的key分别是3,2,1, person4,即使Person实现了Comparable接口,person4依然排在最后,这是为什么?
按照Value的某个字段查询
按照缓存数据对象的某个字段进行查询,是常见的需求,比如要查询出年龄为32的Person。
1.首先在ehcache中设置要查询的属性
<searchable>
<searchAttribute name="age" expression="value.getAge()"/>
</searchable>
这里定义了查询属性age,expression属性表示对value调用哪个方法取值然后进行匹配,这里使用的JavaBean的规范,每个Element的value调用getAge方法。expression属性是可选属性,如下所示:
<searchable>
<searchAttribute name="age"/>
</searchable>
这么写,EhCache解释为查找所有的可查询属性(这里是key和value),然后对每个元素的Key和Value查找getAge方法,如果找到,就通过getAge方法得到对应的值然后进行匹配,这里要注意的是,如果key和value都有getAge方法,那么这种通过这种匹配将抛出异常。在上面的样例数据中,因为第四个元素的Key和Value都是Person对象,都有getAge方法,EhCache不知道取哪个值,因此抛出异常。因此,使用seachAttribute元素时,明确的添加expression属性是一个良好的习惯。
测试五: 根据元素的value的某个字段进行查询
//查询年龄为32的Person
@org.junit.Test
public void test4() {
Query query = cache.createQuery().includeKeys().includeValues();
Attribute<Integer> attribute = cache.getSearchAttribute("age");
query.addCriteria(attribute.eq(32));
Results results = query.execute();
List<Result> resultList = results.all();
}
查询属性抽取
现在回过头来看测试三: 根据Key(复杂类型查询)进行条件查询。EhCache限制查询属性必须是简单类型,也就是说不能把Person传给EhCache让它进行查询,只能把Person的属性传递给EhCache让EhCache按照指定属性进行查询。如果一个对象需要多个字段才能唯一确定一个对象(比如多对多关系的实体中间关系对象,需要两个实体的ID)那么就需要抽取多个属性进行查询。
ehcache.xml配置
<searchable>
<searchAttribute name="personName" class="com.tom.PersonExtractor"/>
<searchAttribute name="personAge" class="com.tom.PersonExtractor"/>
</searchable>
package com.tom;
import net.sf.ehcache.Element;
import net.sf.ehcache.search.attribute.AttributeExtractor;
import net.sf.ehcache.search.attribute.AttributeExtractorException;
public class PersonExtractor implements AttributeExtractor{
@Override
public Object attributeFor(Element element, String attributeName) throws AttributeExtractorException {
Person p = (Person) element.getObjectValue(); //针对Value进行查询
if (attributeName.equals("personAge")) {
return p.getAge();
} else if (attributeName.equals("personName")) {
return p.getName();
}
return null;
}
}
//查询年龄为32,名字为Jack的Person
@org.junit.Test
public void test5() {
Query query = cache.createQuery().includeKeys().includeValues();
Attribute<Integer> ageAttribute = cache.getSearchAttribute("personAge");
Attribute<String> nameAttribute = cache.getSearchAttribute("personName");
query.addCriteria(ageAttribute.eq(32).and(nameAttribute.eq("Jack")));
Results results = query.execute();
List<Result> resultList = results.all();
Assert.assertTrue(resultList != null);
Assert.assertEquals(2, resultList.size());
}
总结:
如果key,value是简单类型,那么可以直接使用key,value查询属性进行查询。如果Key,Value是复杂类型,那么最直观的做法是使用自定义的属性抽取按属性进行查询。
EhCache内置了几种属性抽取的实现
1.KeyObjectAttributeExtractor
2.ValueObjectAttributeExtractor
如果Key,Value是简单类型(即,EhCache直接支持的查询属性类型),那么使用这两种Extractor进行查询
3. net.sf.ehcache.search.attribute.JavaBeanAttributeExtractor
例如:
<searchable>
<searchAttribute name="age"/>
</searchable>
JavaBeanAttributeExtractor的工作方式是首先检查Key中是否有这个属性,然后检查Value,如果属性在Key和Value中都出现,则抛出一场
4. net.sf.ehcache.search.attribute.ReflectionAttributeExtractor
<searchable>
<searchAttribute name="age" expression="value.getAge()"/>
</searchable>
其中的expression的语法是:
1.expression必须以key、value或者element开头,表示查询作用域
2.expression以某个方法调用结束,比如上面的getAge()
3.链式表达方法:value.person.getAge(),这个含义指的是,缓存元素的Value有一个person成员属性,person有个getAge方法,那么通过.来获得级联效果
分享到:
相关推荐
在“ehcache三个小demo”中,我们有三个示例项目,分别展示了Ehcache的不同应用场景和配置方式。 1. **SpringMybatis**: 这个项目的名称暗示了它结合了Spring框架和MyBatis持久层框架。Ehcache在此可能作为数据层...
1.解压缩到目录下,复制ehcache-monitor-kit-1.0.0\lib\ehcache-probe-1.0.0.jar包到application的web-inf/lib目录下 2.将以下配置copy的ehcache.xml文件的ehcache标签中,注:上述链接中说的配置少写了个probe包名...
Ehcache是一个广泛使用的开源Java缓存解决方案,它能够提高应用程序性能,通过缓存数据和对象来减少数据库查询。 【描述解析】:描述中提到“已测试有效的ehcache.xsd文件”,这指的是Ehcache的XML Schema定义文件...
Mybatis-ehcache 1.2.1 是一个集成Mybatis和Ehcache的缓存模块,用于提高Mybatis框架的查询效率。Ehcache是一个广泛使用的Java缓存解决方案,它能够有效地存储和检索数据,减少数据库的负载,提高应用程序性能。在...
Ehcache分为三个主要部分:内存缓存、磁盘存储和缓存复制。内存缓存用于存储最近使用的数据,以实现快速访问;磁盘存储用于保存当内存满时的数据,保证数据不丢失;而缓存复制则是在分布式环境下,确保多节点间的...
赠送jar包:ehcache-3.3.1.jar; 赠送原API文档:ehcache-3.3.1-javadoc.jar; 赠送源代码:ehcache-3.3.1-sources.jar; 赠送Maven依赖信息文件:ehcache-3.3.1.pom; 包含翻译后的API文档:ehcache-3.3.1-javadoc-...
Ehcache是一个广泛使用的开源Java缓存库,它为应用程序提供了高效的内存管理和数据缓存功能。Ehcache的核心目标是提高应用性能,通过将频繁访问的数据存储在内存中,减少对数据库的依赖,从而降低系统负载。这次我们...
在 Hibernate 中,Ehcache 可以作为二级缓存提供服务,将查询结果存储在缓存中,避免重复查询数据库。只需在 Hibernate 配置文件中指定 Ehcache 作为二级缓存提供者即可。 ## 5. Ehcache 的分布式缓存 Ehcache ...
3. **整合 Hibernate 和 Ehcache**:整合 Hibernate 与 Ehcache 可以利用缓存机制来避免频繁的数据库查询,提高应用程序响应速度。通过在 Hibernate 配置文件中添加 Ehcache 配置,可以指定哪些实体或查询结果应该被...
Ehcache是一个高性能的、基于Java的进程内缓存解决方案,它被广泛应用于各种Java应用程序,包括Java EE和轻量级容器。Ehcache的主要优势在于它的快速响应、易用性和丰富的缓存策略。它提供了两种级别的缓存存储:...
二级缓存可以缓存SQL查询的结果,使得后续相同的查询可以直接从缓存中获取,而不是每次都去数据库查询。 EHcache的核心概念包括: 1. **缓存管理器(Cache Manager)**:这是EHcache的顶级组件,负责管理一个或多个...
Ehcache是一个开源的Java缓存库,广泛用于提高应用程序的性能和响应速度,通过存储经常访问的数据在内存中,避免了频繁的数据库查询。它最初由Tomi Triebel开发,现在是Terracotta公司的产品。在版本2.6.5中,...
在MyBatis的Mapper接口或XML映射文件中,我们还可以针对特定的SQL查询启用或禁用二级缓存,例如: ```xml ... SELECT * FROM user WHERE id = #{id} ... ``` 总的来说,`ehcache.xsd`和`ehcache.xml`是...
Ehcache是一款高性能、易用且广泛应用于Java环境中的分布式缓存系统,它极大地提高了应用程序的性能和响应速度。在Spring框架中集成Ehcache,能够实现数据的快速访问,减轻数据库的压力,优化整体系统架构。本文将...
5. **缓存管理和监控**:可以使用Ehcache提供的管理工具或者第三方监控系统进行缓存的监控和管理。 在实际开发中,Ehcache可以和Spring、Hibernate等框架无缝集成,进一步简化缓存管理。例如,使用Spring的缓存抽象...
赠送jar包:ehcache-3.9.9.jar; 赠送原API文档:ehcache-3.9.9-javadoc.jar; 赠送源代码:ehcache-3.9.9-sources.jar; 赠送Maven依赖信息文件:ehcache-3.9.9.pom; 包含翻译后的API文档:ehcache-3.9.9-javadoc-...
通过将数据存储在内存中,ehcache能够显著减少数据库查询次数,从而加快应用响应速度。本文将深入探讨ehcache.xml配置文件中的关键参数及其作用,帮助开发者更有效地管理和优化缓存策略。 ### 1. `defaultCache` ...
在这一版本中,Ehcache 被用作 Mybatis 的二级缓存,以改善数据库查询性能并降低对数据库的压力。接下来,我们将深入探讨 Mybatis 和 Ehcache 的核心概念以及它们如何协同工作。 Mybatis 是一款流行的 Java 数据...
Ehcache 3 是一个广泛使用的开源Java缓存解决方案,特别是在需要高性能、低延迟的数据存储和检索场景下。Ehcache 3 提供了丰富的功能,包括本地内存缓存、磁盘持久化、多线程支持以及在分布式环境中实现集群共享缓存...
`Cache`对象提供了添加、删除、更新和查询缓存项的方法,如`put()`, `get()`, `remove()`, `putIfAbsent()`等。 3. `CacheEntry`: 虽然在API中不直接使用,但它是缓存项的抽象,包含了缓存的键和值。 4. `Element`...