특정 Member의 검색을 할 때 이름만 입력할 수도 있고 이메일만 입력할 수도 있습니다. 입력 할 수 있는 곳이 여러 곳이면 둘 다 입력하거나 둘 다 입력하지 않을 수도 있습니다. 이럴 때 입력을 하느냐 안하느냐에 따라 쿼리가 달라지는데요. 이런것을 Dynamic Query라고 하는것 같습니다.

HQL을 이용해서 이러한 쿼리를 다음과 같이 작성할 수 있습니다.

    public void testDynamicQueryByHQL(){
        insertDatas();
        String name = "s";
        String email = null;

        StringBuffer sb = new StringBuffer("from k_Member m where 1=1");
        if(!StringUtils.isEmpty(name)) sb.append(" and m.name like :name");
        if(!StringUtils.isEmpty(email)) sb.append(" and m.email like :email");
        q = s.createQuery(sb.toString());
        if(!StringUtils.isEmpty(name)) q.setParameter("name", "%" + name + "%");
        if(!StringUtils.isEmpty(email)) q.setParameter("email", "%" + email + "%");

        assertEquals(2, q.list().size());
    }

위와 같은 내용의 쿼리를 Criteria를 사용해서 작성하면 다음과 같이 간결해 집니다. 그리고 @Entity의 name속성에 지정해 준 값을 사용하는 것이 아니라 진짜 클래스 명을 사용해야 합니다.

    public void testDynamicQueryByCriteria(){
        insertDatas();
        String name = "s";
        String email = "keesun@os.net";

        Criteria c = s.createCriteria(KMember.class);
        if(!StringUtils.isEmpty(email)) c.add(Restrictions.eq("email", email));
        if(!StringUtils.isEmpty(name)) c.add(Restrictions.like("name", "%" + name + "%"));

        assertEquals(1, c.list().size());
    }

Criteria의 add 메소드는 인자로 Criterion을 넘겨 주어야 하는데요. Restrictions라는 팩토리를 사용해서 Criterion을 받아 오게 됩니다. Restrictions 클래스에는 쿼리에 덧붙일 수 있는 여러 메소드들이 있습니다.