本文介绍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对象最大
}
按照Value的某个字段查询
<searchable>
<searchAttribute name="age" expression="value.getAge()"/>
</searchable>
<searchable>
<searchAttribute name="age"/>
</searchable>
//查询年龄为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());
}
总结:
<searchable>
<searchAttribute name="age"/>
</searchable>
<searchable>
<searchAttribute name="age" expression="value.getAge()"/>
</searchable>
其中的expression的语法是:

本文详细介绍了EhCache的查询功能,包括数据准备、基本查询、按Value字段查询、结果排序和属性抽取。通过示例展示了如何在ehcache.xml中配置查询属性,并提供了不同类型的查询测试用例,强调了查询属性必须为简单类型。
360

被折叠的 条评论
为什么被折叠?



