利用Specification形式检索缓存数据
利用Specification模式检索缓存数据
随着缓存技术的引入,网站前台的检索速度大大提高,随之而来的一个问题是检索。通常的经验都是写几个Sql语句,但是现在不同,我们需要从内存中检索数据。如何解决呢?我的方式是使用Specification模式 。
Specification模式 把 每一个检索条件转化为对象。我们可以对象进行组合,然后对内存数据进行筛选,这样就可以达到目的。
为什么要采用Specification,因为Specification可让开发人员专注于 【检索条件】的使用。
下面给个例子,供大家参考,源代码在附件
1、年龄规约
public class AgeSpecification extends CompositeSpecification<Member> { private Integer begin; private Integer end; public AgeSpecification(Integer begin,Integer end){ if(begin == null) { this.begin = 0; }else{ this.begin = begin; } if(end == null){ this.end = Integer.MAX_VALUE; }else{ this.end = end; } } public boolean isSatisfiedBy(Member obj) { return obj.getAge() >=begin && obj.getAge() <= end; } }
2、姓名规约
public class NameSpecification extends CompositeSpecification<Member> { private String words; public NameSpecification(String s) { words = s; } public boolean isSatisfiedBy(Member obj) { if(words == null || "".endsWith(words.trim())) return true; return obj.getName().contains(words); } }
3、自定义规约
public class ExpressionSpecification<T> extends CompositeSpecification<T>{ private ExpressionCallback<T> ecp; public ExpressionSpecification(ExpressionCallback<T> ecp) { this.ecp = ecp; } public boolean isSatisfiedBy(T obj) { return ecp.match(obj); } } public interface ExpressionCallback<T> { public boolean match(T obj); }
4、检索的目标对象
public class Member { private String name; private int age; private String mobile; public String getMobile() { return mobile; } public void setMobile(String mobile) { this.mobile = mobile; } public Member(String name,int age,String mobile){ this.name =name; this.age = age; this.mobile = mobile; } public String getName() { return name; } public int getAge() { return age; } public String toString(){ return "姓名:"+ name +" "+"年龄:" + age +" "+"电话:" + mobile; } }
4、测试类
public class TestMemberSearch { private List<Member> members; @Before public void setUp() { members = new LinkedList<Member>(); members.add(new Member("张三", 1, "15013243543")); members.add(new Member("李四", 2, "13013243743")); members.add(new Member("王武", 3, "18613223243")); members.add(new Member("找刘", 4, "18112243245")); members.add(new Member("李八", 5, "13901243647")); members.add(new Member("星七", 6, "18813223272")); members.add(new Member("孙虎", 7, "139263246243")); members.add(new Member("刘琦", 8, "155213243242")); members.add(new Member("张二天", 9, "150132438755")); members.add(new Member("欧阳一清", 10, "13701323249")); members.add(new Member("尧度", 11, "13913243248")); members.add(new Member("真天", 12, "15213243283")); members.add(new Member("海星", 13, "15713243283")); members.add(new Member("范天", 15, "1361323243")); members.add(new Member("林海", 14, "17013243943")); members.add(new Member("杨波", 16, "15013243243")); members.add(new Member("青檬", 17, "15013243243")); members.add(new Member("赵志", 18, "15013243243")); members.add(new Member("得人", 19, "15013243243")); } @After public void tearDown() { members = null; } @Test public void testFindByAgeWhichIsBetween10And20() { Specification<Member> s1 = new AgeSpecification(10, 20); assertEquals(10, filter(members, s1).size()); } @Test public void testFindByName() { Specification<Member> s1 = new AgeSpecification(10, 20); assertEquals(10, filter(members, s1).size()); } @Test public void testFindByAgeAndName() { Specification<Member> age = new AgeSpecification(10, 20); Specification<Member> name = new NameSpecification("赵"); Specification<Member> findByAgeAndName = age.and(name); assertEquals(1, filter(members, findByAgeAndName).size()); } @Test public void testFindByExpression() { Specification<Member> expressionSpeci = new ExpressionSpecification<Member>(new ExpressionCallback<Member>() { public boolean match(Member obj) { return obj.getName().startsWith("赵"); } }); assertEquals(1, filter(members, expressionSpeci).size()); } private static <T> List<T> filter(Collection<T> list, Specification<T> s) { List<T> lists = new LinkedList<T>(); for (T t : list) { if (s.isSatisfiedBy(t)) { lists.add(t); } } return lists; } }