DevBoi

[QueryDsl] Spring 3.0 이상 Jdk 17 세팅 + 설계 본문

Develop/[JPA]

[QueryDsl] Spring 3.0 이상 Jdk 17 세팅 + 설계

HiSmith 2023. 8. 14. 17:36
반응형
buildscript {
  ext {
    queryDslVersion = "5.0.0"
  }
}

plugins {
	id 'java'
  id 'org.springframework.boot' version '3.2.0-SNAPSHOT'
  id 'io.spring.dependency-management' version '1.1.2'
  id "com.ewerk.gradle.plugins.querydsl" version "1.0.10"
}

group = 'com.boiler.flutterbackend'
version = '0.0.1-SNAPSHOT'

java {
	sourceCompatibility = '17'
}


configurations {
  compileOnly {
    extendsFrom annotationProcessor
  }
}
repositories {
	mavenCentral()
	maven { url 'https://repo.spring.io/milestone' }
	maven { url 'https://repo.spring.io/snapshot' }
}


dependencies {
  implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
  implementation 'org.springframework.boot:spring-boot-starter-web'
  implementation 'org.projectlombok:lombok:1.18.26'
  implementation 'org.mariadb.jdbc:mariadb-java-client' // MariaDB
  implementation 'com.h2database:h2'
  testImplementation 'org.springframework.boot:spring-boot-starter-test'
  compileOnly 'org.projectlombok:lombok'
  annotationProcessor 'org.projectlombok:lombok'
  implementation 'com.mysql:mysql-connector-j'
  // === QueryDsl 시작 ===
  implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta'
  annotationProcessor 'com.querydsl:querydsl-apt:5.0.0:jakarta'
  annotationProcessor 'jakarta.annotation:jakarta.annotation-api'
  annotationProcessor 'jakarta.persistence:jakarta.persistence-api'
  // === QueryDsl 끝 ===
}

tasks.named('test') {
	useJUnitPlatform()
}

// Querydsl 설정부
def generated = 'src/main/generated'
querydsl {
  jpa = true
  querydslSourcesDir = generated
}
sourceSets {
  main.java.srcDir generated
}

compileQuerydsl{
  options.annotationProcessorPath = configurations.querydsl
}

configurations {
  compileOnly {
    extendsFrom annotationProcessor
  }
  querydsl.extendsFrom compileClasspath
}

 

중요하게 눈여겨 봐야할 곳은 아래와 같다.

// === QueryDsl 시작 ===
  implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta'
  annotationProcessor 'com.querydsl:querydsl-apt:5.0.0:jakarta'
  annotationProcessor 'jakarta.annotation:jakarta.annotation-api'
  annotationProcessor 'jakarta.persistence:jakarta.persistence-api'
  // === QueryDsl 끝 ===
// Querydsl 설정부
def generated = 'src/main/generated'
querydsl {
  jpa = true
  querydslSourcesDir = generated
}
sourceSets {
  main.java.srcDir generated
}

compileQuerydsl{
  options.annotationProcessorPath = configurations.querydsl
}

configurations {
  compileOnly {
    extendsFrom annotationProcessor
  }
  querydsl.extendsFrom compileClasspath
}
// Querydsl 설정부

 

잘되는지 예제 엔티티와 함께 사용해보자

우선 EntityManager를 사용할 수 있게 쿼리팩토리를 빈으로 등록해줘야한다.

 

querydslconfig

package com.boiler.flutterbackend.app.config;

import com.querydsl.jpa.impl.JPAQueryFactory;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class QuerydslConfig {
  @PersistenceContext
  private EntityManager entityManager;

  @Bean
  public JPAQueryFactory jpaQueryFactory() {
    return new JPAQueryFactory(entityManager);
  }
}

패키지 구조는 아래와 같다.

Entity

package com.boiler.flutterbackend.app.user.entity;

import com.boiler.flutterbackend.app.user.dto.UserDto;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Entity
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "Users")
public class User {
  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  Long id;
  @Column
  String userId;
  @Column
  String img;
  @Column
  String nickname;
  public User(UserDto dto) {
    this.userId = dto.getUserId();
    this.img = dto.getImg();
    this.nickname = dto.getNickname();
  }
}

 

Controller

@GetMapping("/user")
  public List<User> getUser(@RequestParam("userId") String userId){
    return  userService.getFriendsList(userId);
  }

Service

public List<User> getFriendsList(String userId) {
    return userRepository.findByUserId(userId);
  }

Repository

public interface UserRepository extends JpaRepository<User,Long>,UserInterfaceCustom {
}
package com.boiler.flutterbackend.app.user.repo;

import com.boiler.flutterbackend.app.user.entity.User;

import java.util.List;

public interface UserInterfaceCustom {
  List<User> findByUserId(String userId);
}
package com.boiler.flutterbackend.app.user.repo;

import com.boiler.flutterbackend.app.user.entity.QUser;
import com.boiler.flutterbackend.app.user.entity.User;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
@RequiredArgsConstructor
public class UserRepositoryImpl implements UserInterfaceCustom{
  private final JPAQueryFactory queryFactory;

  @Override
  public List<User> findByUserId(String userId) {
    return queryFactory
      .selectFrom(QUser.user)
      .where(QUser.user.userId.ne(userId))
      .stream().toList();
  }

}

 

 

추가적으로 설명하면, repo에 3개의 파일이나 생겨서 이해가 안될 수 있지만

결정적으로 UserRepository를 주입받게 되는데 

이 UserRepository는 UserRepositoryCustomer과 JpaRepository를 상속받아서

내가 구현하지않은 하이버네이트의 기능들을 같이 쓸수있다.

또한 UserRepositoryImpl이 UserInterfaceCustom을 구현하기 때문에 UserRepository만 주입받아도

querydsl로 구현한 것과 하이버 네이트에서 지원하는 기능들을 동시에 사용할 수 있다.

 

나는 이후에 RepositoryImpl -> CustomImpl로 변경하긴 했다.

반응형