Ehcahce 搜索类型简单扩展

Ehcahce 搜索类型简单扩展

简述:

Ehcache自2.4版本后就支持搜索功能,具体的使用语法及规范这里就不说了。在使用的过程中发现三个问题:

1.由于Ehcache搜索的实质就是遍历储存的对象,并用Criteria过滤过滤元素,用Ordering排序结果,最后再用Aggregator计算组合函数。除了Key-Value的检索方式,其他形式的搜索,只要在cache中缓存的结果达到3次方的数量级,效率就很堪忧。因为cache中缓存的对象达到这个数量级时,非Key-Value的检索一次要耗时10毫秒左右,这样的话,一旦有千次以上的检索,性能就会很差。

2.使用中发现一个小BUG,对于String类型的Attribute居然对大小写不敏感。

3.第三条就是要说的重点,ehcahce对于byte[]类型不支持。官方文档中写道,只支持以下几种类型:

  • Boolean

  • Byte

  • Character

  • Double

  • Float

  • Integer

  • Long

  • Short

  • String

  • java.util.Date

  • java.sql.Date

  • Enum

对于第一个问题,我只是简单限制了缓存对象的个数,只要在ehcache.xml对对应的缓存配置下。对于是选择FIFO,LFU还是LRU储存策略,这个我没做过具体研究,也不知道对检索的速度的影响。

第二个问题很小儿科,下文将给出代码。对于第三个问题,虽然支持了byte[]类型但只限于EqualTo和NotEqualTo的检索。因为其他的例如GreaterThan,LessThan 或者ILike对于byte[]的支持,第一没有意义,第二因为要让byte[]实现Comparable又或者要实现相应的算法,必须要自定义一个byte数组的类,对于原本的框架要有较大的改动。


对于ehcahce的search原理简单介绍:

  1. 当你执行query的时候,“储存器”Store将会遍历内存中的每个对象,并将Attribute所有抽取器传递给Query

  2. Query首先按照设置的Criteria来过滤对象,执行的顺序是(AND,NOT,OR)然后是(IlikeEqualToNotEqualToComparableValue),其中ComparableValue顾名思义是比较类的Criteriabetween,GreaterThan,GreaterThanOrEqual,LessThanLessThanOrEqual

  3. 但不管是ILike,EqualTo都要去比对你输入值类型和通过抽取器AttributeExtractor获得该Attribute的类型。这是扩展Attribute支持的重要一环。

  4. 如果比对成功,将会执行对应类型的比较,否则抛出异常。

  5. 将符合Criteria的对象放入result中。

  6. 如果有Ordering就讲result排序。

  7. 如果有Aggregators就计算出相应的组合函数值并放入到result中。


源代码改写:

首先我们要先扩展AttriuteType.java这个类,所有的Attibute类型都是依靠它来识别的。这是一个枚举类,我们需要添加如下代码:

 BYTEA{
        /**
         * {@inheritDoc}
         */
		@Override
		public void validateValue(String name, Object value) throws SearchException {
			if(!(value instanceof byte[])){
				throw new SearchException("Expecting a String value for attribute [" + name + "] but was " 				+ type(value));
			}
		}
    }

并且要加入到它的Mappings中,这个原因就不说了,有点繁琐。在这个类的静态代码块中:

static {
        MAPPINGS.put(Boolean.class, BOOLEAN);
        MAPPINGS.put(Byte.class, BYTE);
        MAPPINGS.put(Character.class, CHAR);
        MAPPINGS.put(Double.class, DOUBLE);
        MAPPINGS.put(Float.class, FLOAT);
        MAPPINGS.put(Integer.class, INT);
        MAPPINGS.put(Long.class, LONG);
        MAPPINGS.put(Short.class, SHORT);
        MAPPINGS.put(String.class, STRING);
        MAPPINGS.put(java.util.Date.class, DATE);
        MAPPINGS.put(java.sql.Date.class, SQL_DATE);
        MAPPINGS.put(byte[].class, BYTEA);//add byte array type
    }

其次就是要改写EqualTo.java这个类的execute方法:

public boolean execute(Element e, Map<String, AttributeExtractor> attributeExtractors) {
		Object attributeValue = attributeExtractors.get(attributeName).attributeFor(e, getAttributeName());
		if (attributeValue == null) {
			return false;
		} else {
			AttributeType attrType = AttributeType.typeFor(getAttributeName(), attributeValue);
			if (!getType().equals(attrType)) {
				throw new SearchException("Expecting attribute of type " + getType().name() + " but was " 			+ attrType.name());
			}

			// if (getType().equals(AttributeType.STRING)) {
			// return ((String) this.value).equalsIgnoreCase((String)
			// attributeValue);
			// } else {
			// return this.value.equals(attributeValue);
			// }

			if (getType().equals(AttributeType.STRING)) {
				return ((String) this.value).equals((String) attributeValue);//make it case sensitive
			} else if (getType().equals(AttributeType.BYTEA)) {//new support type byte array
				return Arrays.equals((byte[]) this.value, (byte[]) attributeValue);
			} else {
				return this.value.equals(attributeValue);
			}
		}
	}

不需要改写NotEqualTo这个类,因为它调用的就是EqualTo这个类。


总的说来这都是对ehcahce的一些小改动,这样脚踏实地的一步步走,还是挺有成就感的。在使用的过程中我还发现ehcachesearch的一个硬伤,Query中的Criteria会跟你的输入的值绑定,例如有这样一个Attibute

 Attribute<Long> oid= Ehcache.getSearchAttribute("m_loid");

又有这样的Criteria

oid.eq(new Long(2)).or(oid.eq(new Long(3))) 

这个Criteria

oid.eq(new Long(3)).or(oid.eq(new Long(3)))

完全不一样,因为Criteria会把值写入到对象中,只就导致同一个表达式不能重用。如果要实现Criteria的重用估计得从新设计框架。


引用:

http://ehcache.org/documentation/user-guide/search







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值