JPA Specification

민지킴·2021년 4월 9일
0

참고 사이트

Spefication

Specification는 검색조건을 추상화한 객체다. 그말은 즉, 검색 조건에 대해 Specification에 생성하고, 이를 통해 다양한 조건의 검색을 할 수 있다는 뜻이다.

Spring Data JPA에서 Repository 또는 Dao의 인터페이스만 정의하면 알아서 해당 구현체를 만들어주며, 해당 구현체에서는 Specification을 지원하기때문에 구현한 Specification 객체를 파라미터에 넣기만 해주면, 해당 조건에 부합되는 객체를 결과값으로 조회가능하다.

조건 검색 방법

Specification 다음과 같은 방식으로 조건 검색을 한다.

  1. Specification을 입력 받도록 Repository 인터페이스를 정의하기

  2. 검색 조건을 모아 놓은 클래스 만들기 (Specifications 객체)

  3. 검색 조건을 조합한 Specification 인스턴스를 이용해서 검색하기

import lombok.extern.slf4j.Slf4j;
import org.springframework.data.jpa.domain.Specification;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.persistence.criteria.Predicate;

@Slf4j
public class AuthInfoSpecs {

    public enum SearchKey {
        SERVICE_NO("serviceno"),
        HOSTING_NO("hostingNo"),
        MALL_ID("mallid");

        private final String value;

        SearchKey(String value) {
            this.value = value;
        }

        public String getValue() {
            return value;
        }

    }


    public static Specification<tb_api_auth_info> searchWith(Map<SearchKey, Object> searchKeyword) {
        return (Specification<tb_api_auth_info>) ((root, query, builder) ->
        {
            List<Predicate> predicate = getPredicateWithKeyword(searchKeyword, root, builder);
            return builder.and(predicate.toArray(new Predicate[0]));
        }

        );
    }

    private static List<Predicate> getPredicateWithKeyword(Map<SearchKey, Object> searchKeyword, Root<tb_api_auth_info> root, CriteriaBuilder builder) {
        List<Predicate> predicate = new ArrayList<>();
        predicate.add(root.get("mallid").isNotNull()); //mallid가 not null인것을 찾겠다는 추가조건.

        for (SearchKey key : searchKeyword.keySet()) {
            switch (key) {
                case MALL_ID:
                    //log.info("mall_id : "+key+" ::: "+key.value);
                    predicate.add(builder.equal(
                            root.get(key.value), searchKeyword.get(key)
                    ));
                    break;
                case SERVICE_NO:
                    //log.info("service_no : "+key+" ::: "+key.value);
                    predicate.add(builder.equal(
                            root.get(key.value), searchKeyword.get(key)
                    ));
                    break;
                case HOSTING_NO:
                    //log.info("hosting_no : "+key+" ::: "+key.value);
                    predicate.add(builder.equal(
                            root.get(key.value), searchKeyword.get(key)
                    ));
                    break;
            }
        }
        return predicate;
    }
}

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

@Service
@Slf4j
public class AuthInfoSearchService {

    @Autowired
    AuthInfoPagingRepository authInfoPagingRepository;

    public AuthResponseVO getAuthInfoData(Map<String, Object> searchRequest, int page, int size) {
        AuthResponseVO authResponseVO = new AuthResponseVO();

        //페이지
        Pageable pageable = PageRequest.of(page,size);
        Page<tb_api_auth_info> pages = null;

        Map<AuthInfoSpecs.SearchKey, Object> searchKeys = new HashMap<>();
        log.info("[parameter] : "+searchRequest.toString());
        try {
            for (String key : searchRequest.keySet()) {
                searchKeys.put(AuthInfoSpecs.SearchKey.valueOf(key.toUpperCase()), searchRequest.get(key));
            }
        }catch(Exception e){
            //잘못된 parameter를 입력하는 경우에 대한 error 처리
            //ex -> hosting_no, service_no, mall_id 이외에
            //hosting_mall_no, kosting_no 같은 경우
            log.info(new LogUtil().catchLog(e));
            return new AuthResponseVO(-1,"Wrong Parameter",null);
        }

        pages = authInfoPagingRepository.findAll(AuthInfoSpecs.searchWith(searchKeys),pageable);
        log.info("[page info] : "+pages.toString());
        if(!pages.hasContent()){
            authResponseVO.setResponseCode(-2);
            authResponseVO.setResponseMsg("No data");
            return authResponseVO;
        }

        authResponseVO.setData(pages.getContent());
        return authResponseVO;

    }

}
profile
하루하루는 성실하게 인생 전체는 되는대로

0개의 댓글