Whiteship's Note

[회사일] DateRange 추가

프로젝트/SLT : 2010.06.14 14:33



오른쪽에 보이는 검색 필드를 MemberSearchingParam에 추가하는데 아무래도 이런 범위 검색 필드는 자주 사용될 것 같더군요.

그래서 별도의 클래스로 분리했습니다.

public class DateRange {

    @DateTimeFormat(iso= DateTimeFormat.ISO.DATE)
    private Date from;

    @DateTimeFormat(iso= DateTimeFormat.ISO.DATE)
    private Date to;

...
}

나머진 요다(?) 조다(?) 라이브러리만 넣어두면 기본 포매터가 동작해서 잘 바인딩 해 줍니다. 아.. 암튼 이번엔 바인딩 얘기가 아니라..  저 클래스 DateRange 얘기입니다.

MemberSearchParam을 MemberDao코드에 적용합니다.

@Repository
public class MemberDaoImpl extends GenericDaoImpl<Member, MemberSearchParam> implements MemberDao {

    protected void applySearchParam(Criteria c, MemberSearchParam searchParam) {
        CriteriaUtils.addOptionalLike(c, "loginId", searchParam.getLoginId());
        CriteriaUtils.addOptionalLike(c, "name", searchParam.getName());
        CriteriaUtils.addOptionalLike(c, "email", searchParam.getEmail());
        CriteriaUtils.addOptionalLike(c, "phoneNumber", searchParam.getPhoneNumber());
        CriteriaUtils.addOptionalLike(c, "jobTiTle", searchParam.getJobTitle());
        CriteriaUtils.addOptionaBetween(c, "birthDay", searchParam.getBirthDayRange());
    }
}

이게 DAO 코드 전부입니다.

유틸 코드로 가야겠네요.

 
   @Test
    public void testOptionalBetween() {
        String dateRangeSearchingFiled = "birthDay";

        CriteriaUtils.addOptionaBetween(c, dateRangeSearchingFiled, null);
        verify(c, times(0)).add(any(Criterion.class));

        reset(c);
        DateRange dateRange = new DateRange();
        CriteriaUtils.addOptionaBetween(c, dateRangeSearchingFiled, dateRange);
        verify(c, times(0)).add(any(Criterion.class));

        reset(c);
        dateRange.setFrom(new Date());
        CriteriaUtils.addOptionaBetween(c, dateRangeSearchingFiled, dateRange);
        verify(c, times(1)).add(Restrictions.ge(any(String.class), dateRange.getFrom()));

        reset(c);
        dateRange.setTo(new Date());
        CriteriaUtils.addOptionaBetween(c, dateRangeSearchingFiled, dateRange);
        verify(c, times(1)).add(Restrictions.between(any(String.class), dateRange.getFrom(), dateRange.getTo()));

        reset(c);
        dateRange.setFrom(null);
        CriteriaUtils.addOptionaBetween(c, dateRangeSearchingFiled, dateRange);
        verify(c, times(1)).add(Restrictions.le(any(String.class), dateRange.getTo()));
    }

장황해 보이지만 별거 없는 테스트 입니다.

  
 public static void addOptionaBetween(Criteria c, String fieldName, DateRange dateRange) {
        if(dateRange == null)
            return;

        if(dateRange.getFrom() != null && dateRange.getTo() != null){
            c.add(Restrictions.between(fieldName, dateRange.getFrom(), dateRange.getTo()));
        }

        if(dateRange.getFrom() != null && dateRange.getTo() == null){
            c.add(Restrictions.ge(fieldName, dateRange.getFrom()));
        }

        if(dateRange.getFrom() == null && dateRange.getTo() != null){
            c.add(Restrictions.le(fieldName, dateRange.getTo()));
        }
    }

이 코드를 테스트하고 있죠. 그런데 코드가 좀;; Don't Tell, Ask가 생각나더군요. 저런 조건 문을 inline 뭐시기 리팩토링으로 분리할 수도 있지만 그보다 일단 if 조건문에 들어있는 내용이 들어있어야 할 위치가... DateRange가 되어야 할 것 같단 생각이 듭니다.

머 일단 if안에 있는 조건문 들을 extract method 리팩토링으로 빼냅니다. 이런 리팩토링을 인라인 머시기 리팩토링이라고 했던것 같은데 잊어버렸네요. @_@;;

 
   public static void addOptionaBetween(Criteria c, String fieldName, DateRange dateRange) {
        if(dateRange == null)
            return;

        if(hasFromAndTo(dateRange)){
            c.add(Restrictions.between(fieldName, dateRange.getFrom(), dateRange.getTo()));
        }

        if(hasFromOnly(dateRange)){
            c.add(Restrictions.ge(fieldName, dateRange.getFrom()));
        }

        if(hasToOnly(dateRange)){
            c.add(Restrictions.le(fieldName, dateRange.getTo()));
        }
    }

    private static boolean hasToOnly(DateRange dateRange) {
        return dateRange.getFrom() == null && dateRange.getTo() != null;
    }

    private static boolean hasFromOnly(DateRange dateRange) {
        return dateRange.getFrom() != null && dateRange.getTo() == null;
    }

    private static boolean hasFromAndTo(DateRange dateRange) {
        return dateRange.getFrom() != null && dateRange.getTo() != null;
    }

그럼 이렇게 되는데 여기서 아래 세개의 static 메서드를 DateRange 쪽 멤버 메서드로 옯겨줍니다.

public class DateRange {

    @DateTimeFormat(iso= DateTimeFormat.ISO.DATE)
    private Date from;

    @DateTimeFormat(iso= DateTimeFormat.ISO.DATE)
    private Date to;

...

    public boolean hasToOnly(DateRange dateRange) {
        return dateRange.getFrom() == null && dateRange.getTo() != null;
    }

    public boolean hasFromOnly(DateRange dateRange) {
        return dateRange.getFrom() != null && dateRange.getTo() == null;
    }

    public boolean hasFromAndTo(DateRange dateRange) {
        return dateRange.getFrom() != null && dateRange.getTo() != null;
    }
}

그리고 CriteriaUtils 코드를 수정해주면 되죠.

  
 public static void addOptionaBetween(Criteria c, String fieldName, DateRange dateRange) {
        if(dateRange == null)
            return;

        if(dateRange.hasFromAndTo(dateRange)){
            c.add(Restrictions.between(fieldName, dateRange.getFrom(), dateRange.getTo()));
        }

        if(dateRange.hasFromOnly(dateRange)){
            c.add(Restrictions.ge(fieldName, dateRange.getFrom()));
        }

        if(dateRange.hasToOnly(dateRange)){
            c.add(Restrictions.le(fieldName, dateRange.getTo()));
        }
    }

마지막으로 테스트 한번 돌려주면 깔끔하게 끝~









저작자 표시
신고
top

TAG



: 1 : ··· : 54 : 55 : 56 : 57 : 58 : 59 : 60 : 61 : 62 : ··· : 2638 :





티스토리 툴바