본문 바로가기

Programming👩🏻‍💻/AxBoot

QueryDSL

QueryDSL?

오픈소스 프로젝트로 복잡한 Creteria를 대체하는 JPQL빌더이다.

복잡한 쿼리와 동적쿼리를 깔끔하게 해결해주고 쿼리를 자바 코드로 작성할 수 있다. 따라서 문법오류를 컴파일 단계에서 잡아줄 수 있다.


-Creteria는 Java코드를 이용해 JPQL을 작성할 수 있게 도와주는 타입 세이프(Type-Safe: 타입에 안정적 즉 어떠한 오퍼레이션(또는 연산)도 정의되지 않은 결과를 내놓지 않은 것이다. 예측불가능한 결과를 내지 않는 것을 뜻함)를 제공하는 쿼리이다. SQL 쿼리를 대체해 HQL, JPQL을 자바 코드로 이용해 작성할 수 있게 해 준다.

 

-JPQL는 JPA의 일부로 정의된 플랫폼 독립적인 객체지향 쿼리이다.

SQL에 크게 영향을 받아 SQL문과 비슷하지만 데이터베이스의 테이블에 직접 연결되는 것이 아니라

JPA 엔티티에 대해 동작한다. 


 

●DB 'Company'에 대한 개체 등록 및 삭제/수정/조회 기능 만들기

1. 진행하고 있는 프로젝트에서 Companyservice단에서 상속된

BaseService에 QueryDSL의 개체를 등록한 후,

import java.io.Serializable;
public class BaseService<T, ID extends Serializable> extends AXBootBaseService<T, ID> {
    protected QUserRole qUserRole = QUserRole.userRole;
    protected QAuthGroupMenu qAuthGroupMenu = QAuthGroupMenu.authGroupMenu;
    protected QCommonCode qCommonCode = QCommonCode.commonCode;
    protected QUser qUser = QUser.user;
    protected QProgram qProgram = QProgram.program;
    protected QUserAuth qUserAuth = QUserAuth.userAuth;
    protected QMenu qMenu = QMenu.menu;
    protected QCommonFile qCommonFile = QCommonFile.commonFile;
    protected QCompany qCompany = QCompany.company;
    protected AXBootJPAQueryDSLRepository<T, ID> repository;
    public BaseService() {
        super();
    }
    public BaseService(AXBootJPAQueryDSLRepository<T, ID> repository) {
        super(repository);
        this.repository = repository;
    }
}

 

 

2. CompanyService.java에 사용할 QueryDSL 기능을 추가함.

   //QueryDSL
    public List<Company> getByQueryDsl(RequestParams<Company> requestParams) {
        String company = requestParams.getString("company", "");
        String ceo = requestParams.getString("ceo", "");
        String bizno = requestParams.getString("bizno", "");
        BooleanBuilder builder = new BooleanBuilder();
        if (isNotEmpty(company)) {
            builder.and(qCompany.companyNm.eq(company));
        }
        if (isNotEmpty(ceo)) {
            builder.and(qCompany.ceo.eq(ceo));
        }
        if (isNotEmpty(bizno)) {
            builder.and(qCompany.bizno.eq(bizno));
        }
        List<Company> companyList = select()
                .from(qCompany)
                .where(builder)
                .orderBy(qCompany.companyNm.asc())
                .fetch();
        return companyList;
    }

    @Transactional
    public void saveByQueryDsl(List<Company> request) {
        for (Company company: request) {
            if (company.isCreated()) {
                save(company);
            } else if (company.isModified()) {
                update(qCompany)
                        .set(qCompany.companyNm, company.getCompanyNm())
                        .set(qCompany.ceo, company.getCeo())
                        .where(qCompany.id.eq(company.getId()))
                        .execute();
            } else if (company.isDeleted()) {
                delete(qCompany)
                        .where(qCompany.id.eq(company.getId()))
                        .execute();
            }
        }
    }

3. CompanyController.java에 @ApiImplicitParams(저장된 테이블 컬럼에 데이터 조회로 테스트할 수 있는 기능?)

@RequestMapping(value = "/QueryDsl", method = RequestMethod.GET, produces = APPLICATION_JSON)
@ApiImplicitParams({
        @ApiImplicitParam(name = "company", value = "회사명", dataType = "String", paramType = "query"),
        @ApiImplicitParam(name = "ceo", value = "대표자", dataType = "String", paramType = "query"),
        @ApiImplicitParam(name = "bizno", value = "사업자번호", dataType = "String", paramType = "query")
})
public Responses.ListResponse list2(RequestParams<Company> requestParams) {
    List<Company> list = companyService.getByQueryDsl(requestParams);
    return Responses.ListResponse.of(list);
}
@RequestMapping(value = "/QueryDsl", method = {RequestMethod.PUT}, produces = APPLICATION_JSON)
public ApiResponse save2(@RequestBody List<Company> request) {
    companyService.saveByQueryDsl(request);
    return ok();
}

 

4. company.jsp에서 화면단에 해당하는 값을 추출하기 위해서 각 input태그에 NAME과 ID를 같은 이름으로

요소로 추가한다.

<div role="page-header">
    <ax:form name="searchView0">
        <ax:tbl clazz="ax-search-tbl" minWidth="500px">
            <ax:tr>
                <ax:td label='회사명' width="300px">
                    <input type="text" name="company" id="company" class="form-control" />
                </ax:td>
                <ax:td label='대표자' width="300px">
                    <input type="text" name="ceo" id="ceo" class="form-control" />
                </ax:td>
                <ax:td label='사업자번호' width="300px">
                    <input type="text" name="bizno" id="bizno" class="form-control" />
                </ax:td>
            </ax:tr>
        </ax:tbl>
    </ax:form>
    <div class="H10"></div>
</div>

 

5. company.js에서 jsp에서 추가했던 name/id 요소로 값을 가져올 수 있게 소스코드를 추가.

fnObj.searchView = axboot.viewExtend(axboot.searchView, {
    initView: function () {
        this.target = $(document["searchView0"]);
        this.target.attr("onsubmit", "return ACTIONS.dispatch(ACTIONS.PAGE_SEARCH);");
        this.company = $("#company");
        this.ceo = $("#ceo");
        this.bizno = $("#bizno");
    },
    getData: function () {
        return {
            pageNumber: this.pageNumber,
            pageSize: this.pageSize,
            company: this.company.val(),
            ceo: this.ceo.val(),
            bizno: this.bizno.val()
        }
    }
});

 

●데이터 수정 기능

 

1. company.js에서 PAGE_SAVE의 type : put영역에 querydsl 경로를 추가하여 수정기능을 완성한다.

   PAGE_SAVE: function (caller, act, data) {
        var saveList = [].concat(caller.gridView01.getData()); //modified삭제함
        saveList = saveList.concat(caller.gridView01.getData("deleted"));

        axboot.ajax({
            type: "PUT",
 //         url: "/api/v1/company",
            url: "/api/v1/company/QueryDsl",
            data: JSON.stringify(saveList),
            callback: function (res) {
                ACTIONS.dispatch(ACTIONS.PAGE_SEARCH);
                axToast.push("저장 되었습니다");
            }
        });
    },

 

●데이터 삭제기능

getData: function (_type) {
        var list = [];
        var _list = this.target.getList(_type);

        if (_type == "modified" || _type == "deleted") {
            list = ax5.util.filter(_list, function () {
               // delete this.deleted;
              //  return this.key;
              return this.id; // 객체안에는 key값이 없으므로 id값을 받아온다.
            });
        } else {
            list = _list;
        }
        return list;
    },

인텔리제이 커뮤니티 버전으로 화면단을 실시간 업데이트할 수 있는 dependency

<dependency>
    <groupId>org.assertj</groupId>
    <artifactId>assertj-core</artifactId>
    <version>3.12.2</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <optional>true</optional>
</dependency>

'Programming👩🏻‍💻 > AxBoot' 카테고리의 다른 글

Banner / Logging / Excel download  (0) 2021.04.30
jsfiddle  (0) 2021.04.23
*중요 디버깅, 단위테스트  (0) 2021.04.22
Mybatis연동  (0) 2021.04.19
Mac 맥) Maven 설치 및 환경 변수 설정  (0) 2021.04.19