如何在EHCache的字符串列表值中高效搜索并返回Java对象?
在EHCache中优化列表属性的搜索方案
问题场景
缓存结构为:键是ID,值是包含ArrayList<String>类型邮箱列表的VzdData对象,需根据邮箱地址搜索对应的完整VzdData实例。当前通过将邮箱列表拼接为分号分隔字符串,再用ilike模糊匹配实现,寻求更优方案。
当前实现代码
属性提取器与缓存配置
public static class EMailAttributeExtractor implements AttributeExtractor { public Object attributeFor(Element element) { VzdData vzdData = ((VzdData) element.getObjectValue()); return String.join(";", vzdData.getServiceData().getMail()); } @Override public Object attributeFor(Element element, String attributeName) throws AttributeExtractorException { return this.attributeFor(element); } } Searchable searchable = new Searchable(); searchable.addSearchAttribute(new SearchAttribute().name("email").className(EMailAttributeExtractor.class.getName())); searchable.setAllowDynamicIndexing(true);
查询方法
public VzdData getVzdDatabyEMail(String email) throws VZDException { log.entry(email); VzdData vzdData = null; Attribute<String> emailSearchAttribute = this.cache.getSearchAttribute("email"); Query query = this.cache.createQuery().addCriteria(emailSearchAttribute.ilike("*" + email + "*")); query.includeValues(); Results results = query.execute(); List<Result> resultList = results.all(); return log.exit(vzdData); }
优化方案:利用EHCache集合类型属性的原生搜索支持
EHCache的搜索API原生支持对集合类型属性执行精确匹配,无需拼接字符串,性能和准确性更优。
1. 修改属性提取器,直接返回邮箱列表
无需将列表拼接为字符串,直接返回List<String>类型的邮箱集合:
public static class EMailAttributeExtractor implements AttributeExtractor { @Override public Object attributeFor(Element element) { VzdData vzdData = ((VzdData) element.getObjectValue()); return vzdData.getServiceData().getMail(); // 返回原列表集合 } @Override public Object attributeFor(Element element, String attributeName) throws AttributeExtractorException { return this.attributeFor(element); } }
2. 调整查询逻辑,使用contains精确匹配
替换ilike为contains条件,实现集合元素的精确匹配:
public VzdData getVzdDatabyEMail(String email) throws VZDException { log.entry(email); VzdData vzdData = null; Attribute<List<String>> emailSearchAttribute = this.cache.getSearchAttribute("email"); // 使用contains条件匹配集合中的精确邮箱 Query query = this.cache.createQuery().addCriteria(emailSearchAttribute.contains(email)); query.includeValues(); Results results = query.execute(); List<Result> resultList = results.all(); // 处理匹配结果(示例取第一个匹配项) if (!resultList.isEmpty()) { vzdData = (VzdData) resultList.get(0).getValue(); } return log.exit(vzdData); }
优化优势
- 性能提升:避免字符串拼接开销,
contains基于集合索引匹配,比模糊ilike效率更高; - 结果准确:不会出现模糊匹配导致的误命中(如不会将
test@test.de与test这类子串匹配); - 逻辑简洁:无需处理通配符与字符串拼接,代码更直观。
如果需要支持邮箱的模糊匹配(如按域名搜索),可以进一步拆分邮箱属性(如提取域名作为单独搜索属性),但精确匹配单个邮箱时,上述方案为最优解。
内容的提问来源于stack exchange,提问作者Tobias Wolf
相关产品推荐
相关产品推荐

