반응형
250x250
Notice
Recent Posts
Recent Comments
Link
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Archives
Today
Total
관리 메뉴

샘오리_개발노트

[JAVA] JPA 활용법 -2 (QueryDSL 활용해보기) 본문

개발자 전향 프로젝트

[JAVA] JPA 활용법 -2 (QueryDSL 활용해보기)

샘오리 2022. 12. 6. 14:45
728x90
반응형

https://samori.tistory.com/52

 

[JAVA] JPA 활용법 -1 (QueryDSL 적용해보기)

QueryDSL이란? Spring Boot Data JPA 는 쿼리문을 직접 짜지 않아도 함수명만 알맞게 적어주면 쿼리를 자동으로 짜주는 ORM으로 유명한데 사실상 조금만 복잡하고 동적인 쿼리를 짜려고만 해도 JPQL등을

samori.tistory.com

지난 글에 이어 오늘은 QueryDsl을 활용해서 기본적인 조회와 수정을 진행해보려고 한다.

첫번 째로 구현하려고 하는 로직은 사용자가 입력한 값을 토대로 DB에 접속하여 일치하는 데이터를 조회하는 작업이다.

 

JPA 기준으로 DTO를 설정해주고

예시

@Getter
@Setter
@Entity
@Table(name = "테이블명")
public class 클래스명 {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "칼럼명", insertable = false)
    private Integer 변수명;
    
    @Column(name = "칼럼명")
    private String 변수명; 	  
    

}

Controller에서 기존에 받던대로 요청을 받아서 SERVICE로 뿌려주고

SERVICE는 기존에 받던대로 요청을 받아서 QueryDSL전용 인터페이스를 호출하게 된다.

*일반 JpaRepository를 상속받은 인터페이스는 사용하지 않는다

 

SERVICE 예시

   //생성자 주입
    private final QueryDSL인터페이스 QueryDSL인터페이스;

   //생성자

   //함수
    public List<Dto명> 함수명(String 변수명) {
        return QueryDSL인터페이스.함수명(변수명);
    }

 

QueryDSL전용 인터페이스

예시

public interface 인터페이스명 {
    
    List <Dto명> 함수명 (String 변수명);

}

QueryDSL전용 인터페이스 구현체

예시

@Repository
public class 구현체 implements 인터페이스 {

    //QueryDSL 생성자 주입
    private final JPAQueryFactory jpaQueryFactory; 
    
    //생성자
    public 구현체(JPAQueryFactory jpaQueryFactory) {
        this.jpaQueryFactory = jpaQueryFactory;
       
    // 사용자가 입력한 값으로 DB를 조회해서 일치하는 것을 찾아내는 검색 로직   
    @Override
    public List<Dto명> 함수명(String 변수명) {
        List<Dto명> 리스트로 담을 변수명 = jpaQueryFactory
                .selectFrom(스태틱으로 불러온 QueryDSL 전용 DTO의 참조변수)
                .where(
                        전용 DTO의 참조변수.칼럼명.toUpperCase().contains(변수명.toUpperCase())
                        .or(전용 DTO의 참조변수.칼럼명.toUpperCase().contains(변수명.toUpperCase()))
                                )
                )
                .orderBy(전용 DTO의 참조변수.정렬할 때 기준으로 삼고 싶은 칼럼.asc())
                .fetch();
        return 리스트로 담을 변수명;
    }
}

이런식으로 리스트에 담아서 return을 해주게 되면 원래 받던대로 받아서 view단에 뿌려주기만 하면 되는 것이다.

이 조회(검색) 쿼리에서 눈여겨 볼 것은

 

1. 스태틱으로 불러온 QueryDSL 전용 DTO의 참조변수

2. toUpperCase()

3. contains

이다.

 

1. 먼저 스태틱으로 불러온 QueryDSL 전용 DTO의 참조변수는 아래를 의미한다.

제대로 compile했다면 기존 Dto를 가져다가 QueryDSL이 자동으로 만들어주는 QueryDSL 전용 Dto에서 찾아볼 수 있다.

저 static final로 된 전용 Dto의 참조변수는 italic으로 되어있어서 구분할 수 있는데 저 참조변수를 가져다가 쓰는것이다.

 

2. toUpperCase를 쓰게 되면 대문자로 변경해주는 함수로 대소문자 구분없이 검색을 하기 위해서 입력한 값과 찾을 값의 대소문자를 통일해주는 작업이다.

 

3.  contains는 해당 입력값이 포함되어있는지 찾는 함수인데 like와도 비슷하다.

 

둘의 차이는 아래와 같다. 

like : %

 -> 일치하거나 뒤에 붙어있으면 된다. 예: 키워드(way) => sub"way"

contains : %값%

 -> 포함만 되어있으면 된다. 예: 키워드(pl) => Ap"pl"e

 


조회(검색)은 그렇다 치고 수정은 어떻게 하는 것일까?

 

@Override
@Transactional 
public void 함수명(매개변수로 받은 DTO명 참조변수) {

       jpaQueryFactory.update(스태틱으로 불러온 QueryDSL 전용 DTO의 참조변수)
              .set(QueryDSL 전용 DTO의 참조변수.변경하고 싶은 칼럼, "매개변수로 받은 DTO의 참조변수.칼럼명")
              .set(QueryDSL 전용 DTO의 참조변수.변경하고 싶은 칼럼, "매개변수로 받은 DTO의 참조변수.칼럼명")
              .set(QueryDSL 전용 DTO의 참조변수.변경하고 싶은 칼럼, "매개변수로 받은 DTO의 참조변수.칼럼명")
              .where(QueryDSL 전용 DTO의 참조변수.칼럼명.eq(매개변수로 받은 DTO의 참조변수.칼럼명))
              .execute();
              
    }

여기서 눈여겨볼 것은 아래와 같다.

1. @Transactional 어노테이션

 

위 어노테이션은 데이터베이스의 상태를 변경하는 작업 또는 한번에 수행되어야 하는 연산들 수행할 때 begin, commit 을 자동으로 수행해주고 예외 발생 시 rollback 처리를 자동으로 수행해주기에 사용한다.

 

2. set

 

여러칼럼을 한번에 변경하고 싶을 때 set을 하나씩 해줘야하는 번거로움이 있다.

기본적으로는 .set(바꿀칼럼, 바꿀값) 이다.

 

3. 매개변수로 받은 DTO명과 그 참조변수

매개변수로 기본형 데이터 뿐만 아니라 DTO로도 받을 수 있다.

예를 들어 Form을 통해 이것저것 한번에 보낸다면 DTO라는 정해진 규격안에 담아서 보낼 수도 있는 것이다.

이경우 다른 DTO를 바라보고 있지만 참조변수의 이름은 같을 수 있으므로 임의로 구분짓기 위해 달리 써줄 수도 있다.

 

예를 들어 

위와 같이 QueryDSL 전용 DTO의 참조변수도 codeDto이고 

기존에 사용하던 CodeDto의 참조변수도 codeDto라면 이름이 동일하므로 잘못 들어갈 수 있다. 

 

매개변수의 참조변수 이름은 임의로 변경할 수 있으므로 

받을 때는  

public void 함수명(CodeDto codeDto) 로 하는 것이 아닌

public void 함수명(CodeDto updateDto) 로 할 수도 있는 것이다.

 

이렇게 되면 

 

public void 함수명(CodeDto updateDto) {
       jpaQueryFactory.update(codeDto)
              .set(codeDto.CodeNameKo, updateDto.CodeNameKo)
              .where(codeDto.codeNo.eq(updateDto.codeNo))
              .execute();

 

4. execute

 

말그대로 데이터베이스의 상태를 변경하는 작업을 실행하라는 명령어이다. 일종의 commit과 비슷하지 않을까?

 

 

참고로 QueryDSL은 INSERT를 자체적으로 제공하고 있지 않아서 EntityManager을 이용해야 한다.

CREATE과 DELETE는 쉬우므로 하나로 묶어서 다음편에 설명하겠다.

728x90
반응형
Comments