Spring Data JPA๋ฅผ ์ฌ์ฉํ๋ค๋ณด๋ฉด Mybatis์ ๋์ ์ฟผ๋ฆฌ๊ฐ ๊ทธ๋ฆฌ์ ์ง ๋๊ฐ ์๋ค.
Select ๊ธฐ๋ฅ์ ๊ฒฝ์ฐ Database์ ๋์ ์ฟผ๋ฆฌ๊ฐ ํ์์ ์ธ๋ฐ, ์ด๋ด๋ QueryDSL์ ์ฌ์ฉํ์ฌ Spring Data JPA์ ์ฐ๋ํ๋ฉด ๋์ ์ฟผ๋ฆฌ๊ฐ ๊ฐ๋ฅํ๋ค!
Spring Boot + Maven ํ๊ฒฝ์์ ์ค์ ๋ฐฉ๋ฒ์ ์ ๋ฆฌํด๋ณด๋ ค๊ณ ํ๋ค.
<dependencies>
<!-- Querydsl Dependency-->
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
</dependency>
<!-- Querydsl Dependency-->
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>com.mysema.maven</groupId>
<artifactId>apt-maven-plugin</artifactId>
<version>1.1.3</version>
<executions>
<execution>
<goals>
<goal>process</goal>
</goals>
<configuration>
<outputDirectory>target/generated-sources/java</outputDirectory>
<processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
// Config Package ํ์์ ํ๊ฑฐ๋ JPA ์ ๊ด๋ จ๋ Package ํ์์ Config Package๋ฅผ ๋ง๋ค์ด์ ์ค์ ํ๋ค.
// ํ์๋ repository.config Package ํ์์ ์์ฑํ์๋ค.
@Configuration
public class JPAConfig {
@PersistenceContext
private EntityManager entityManager;
@Bean
public JPAQueryFactory jpaQueryFactory() {
return new JPAQueryFactory(entityManager);
}
}
์ด์์ผ๋ก QueryDSL์ ์ฌ์ฉํ ๊ธฐ๋ณธ์ ์ธ ์ค์ ์ ๋ชจ๋ ๋ง์ณค๋ค!
๋ค์์ผ๋ก๋ Spring Data JPA์ ์ฐ๋ํ์ฌ CustomRepository ๋ฅผ ์์ฑํ๋ ๋ฒ์ ์ ๋ฆฌํด๋ณด๊ฒ ๋ค.
Spring Data JPA + QueryDSL Repository ์์ฑ์ ์์์ ๊ธฐ๋ณธ์ ์ธ ๊ตฌ์กฐ๋ ์๋์ ๊ทธ๋ฆผ์ ์ฐธ๊ณ ํด์ผํ๋ค.
// extend์ QueryDSL Custom ์ธํฐํ์ด์ค๊ฐ ์ถ๊ฐ๋์๋ค.
public interface UserInfoRepository
extends JpaRepository<UserInfo, Long>, UserInfoRepositoryCustom {
@Override
@EntityGraph(attributePaths = {"userDetailInfo"})
Optional<UserInfo> findById(Long aLong);
}
public interface UserInfoRepositoryCustom {
List<UserInfo> findByRequestPayload(UserInfoSelectRequestPayload payload,
Pageable pageable);
}
@Repository
@RequiredArgsConstructor
public class UserInfoRepositoryImpl implements UserInfoRepositoryCustom {
private final JPAQueryFactory queryFactory;
@Override
public List<UserInfo> findByRequestPayload(UserInfoSelectRequestPayload payload,
Pageable pageable) {
return queryFactory.selectFrom(userInfo)
.where(likeName(payload.getName()),
eqSex(payload.getSex()),
likeDowntownName(payload.getDowntownName()))
.leftJoin(userInfo.downtownInfo, downtownInfo).fetchJoin()
.leftJoin(userInfo.userDetailInfo, userDetailInfo).fetchJoin()
.offset(pageable.getPageNumber())
.limit(pageable.getPageSize())
.fetch();
}
private BooleanExpression likeName(String name) {
if (ObjectUtils.isEmpty(name))
return null;
return userInfo.name.like(name);
}
private BooleanExpression likeName(int name) {
String findName = String.valueOf(name);
if (ObjectUtils.isEmpty(findName))
return null;
return userInfo.name.like(findName);
}
private BooleanExpression eqSex(Sex sex) {
if (ObjectUtils.isEmpty(sex))
return null;
return userInfo.userDetailInfo.sex.eq(sex);
}
private BooleanExpression likeDowntownName(String downtownName) {
if (ObjectUtils.isEmpty(downtownName))
return null;
return userInfo.downtownInfo.name.like(downtownName);
}
}
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class UserInfoServiceImpl implements IUserInfoService {
private final UserInfoRepository userInfoRepository;
@Override
public UserInfoSelectResponsePayload userInfoSelect(UserInfoSelectRequestPayload payload, Pageable pageable) {
// ์ฌ๊ธฐ์ ์ฌ์ฉํ๋ค!!!!
List<UserInfo> findUserInfoList = userInfoRepository.findByRequestPayload(payload, pageable);
List<UserInfoDTO> userInfoDTOList = findUserInfoList.stream()
.map(UserInfoDTO::new)
.collect(Collectors.toList());
UserInfoSelectResponsePayload userInfoSelectResponsePayload = new UserInfoSelectResponsePayload();
userInfoSelectResponsePayload.setUserInfoList(userInfoDTOList);
return userInfoSelectResponsePayload;
}
}
Spring Data JPA + QueryDSL ์ ๊ธฐ๋ณธ ์ค์ ๋ฐ ๊ตฌํ์ ๋ชจ๋ ์ ๋ฆฌํ์๋ค.
QueryDSL ์ CustomImpl Class์์ ๊ตฌํ ์ฝ๋์ ์ฌ๋ฌ๊ฐ์ง ๊ธฐ๋ฒ์ด ๋์๋๋ฐ ๊ฐ๋ตํ๊ฒ ์ค๋ช
ํ์๋ฉด QueryFactory ๋ฅผ ์ด์ฉํ์ฌ ํ
์ด๋ธ๋ค์ SQL๋ฌธ ์ฒ๋ผ ์กฐํํ๊ณ LeftJoin.fetchJoin() Method๋ฅผ ํ์ฉํ์ฌ N+1 ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ๊ฒ์ด๋ค.
๋ค์ ์ ๋ฆฌ์์ ์์ธํ๊ฒ ๋ค๋ค๋ณด๋๋ก ํ๊ฒ ๋ค.