querydsl 사용 깃 프로젝트
https://github.com/SpartaPhotoGet/gloryoneteam.git
1. build.gradle 환경 세팅
[참고사이트] https://velog.io/@jkijki12/Spring-QueryDSL-%EC%99%84%EB%B2%BD-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0
2. gradle 내, other에서 compile.java 실행
=> 해당 작업으로 build -> generated -> querydsl 생성됨
3. 사용하고자하는 repository에 자신이 원하는 기능메서드를 추가한 customrepository 상속시킴
사용목적
>> 클라이언트 측에서 검색창에 임의의 값을 입력하였을 때 member에 해당하는 folder들 중, folder_name과 tag_name를 포함하는 값이 있을 시 해당하는 폴더들을 리스트 형식으로 반환하고자 함.
// 기존 폴더레포지토리에 커스텀 폴더레포지토리를 상속시켜준다
public interface FolderRepository extends JpaRepository<Folder, Long>, FolderRepositoryCustom {
List<Folder> findAllByMemberOrderByDateDesc(Member member);
List<Folder> findByMember(Member member);
}
// 커스텀 레포지토리에 메소드 쿼리문을 작성한다.
public interface FolderRepositoryCustom {
List<Folder> findByKeyword(String keyword, Member member);
}
4. 클래스 파일 생성 후, 레포지토리 선언 + customrepository implements 실행 (JPA쿼리 의존성 주입도 실행)
그 후 원하는 로직작성
+조인하는 과정에서 쿼리성능 최적화하는 법 찾음!
아래에 주석으로 별도 추가해놓았음
// 폴더레포지토리커스텀을 해당 클래스에 implements한다. 그 후 해당 클래스를 @Repository로 주입하고 @RequriedArgsConstructor로 JPAQueryFactory를 주입한다. (사용하기 위해서)
@RequiredArgsConstructor
@Repository
public class FolderRepositoryImpl implements FolderRepositoryCustom {
private final JPAQueryFactory queryFactory;
// 여기서 커스텀 레포지토리에 적힌 것을 오버라이딩한다.
@Override
public List<Folder> findByKeyword(String keyword, Member member) {
QFolder folder = QFolder.folder;
QFolderTag folderTag = QFolderTag.folderTag;
List<FolderTag> folderTagList = queryFactory.selectFrom(folderTag) // 폴터태그 모든 것을 리스트에 담는다.
//쿼리성능 최적화
.leftJoin(folderTag.folder,folder).on(folder.member.eq(member)) 해당코드로 교체 후
where절에 있는 .where(folder.member.eq(member)) 제거 시 쿼리성능이 더욱 높아짐
//추가로, or절을 활용하여 search메소드를 안 써도 되는 방법은 아래와 같다.
.where(folder.folderName.contains(keyword)
.or(folderTag.tagName.contains(keyword))
)
.leftJoin(folderTag.folder,folder).fetchJoin() // 폴더테그의 폴더와 폴더를 leftjoin으로 연걸한다.
// fetchJoin을 활용해서 N+1문제를 해결할 수 있다. 폴더태그와 폴더를 함께 조회해서 지연로딩을 X로 만든다.
.where(folder.member.eq(member)) //본인 쓴 폴더만 조회 (Q폴더가 매개변수 멤버와 동일한지 조건문)
.where(search(keyword)) //파일이름 or 태그 검색 / search메소드 동작
.orderBy(folder.date.desc()) // 날짜 내림차순 정렬
.fetch(); // 기존에 조인된 것을 다시 해제
return folderTagList.stream()
.map(FolderTag::getFolder)
.distinct() // 중복제거
.collect(Collectors.toList());
}
private BooleanBuilder search(String keyword){
BooleanBuilder booleanBuilder = new BooleanBuilder();
if(hasText(keyword)){
booleanBuilder.or(folder.folderName.contains(keyword));
}
if(hasText(keyword)){
booleanBuilder.or(folderTag.tagName.contains(keyword));
}
return booleanBuilder;
}
}
5. 위 로직을 사용하길 희망하는 곳에서 사용하면 됨
@Service
@RequiredArgsConstructor
public class SearchFolderService {
private final FolderRepository folderRepository;
@Transactional(readOnly = true)
public List<FolderSearchResDto> searchTagFolder(String query, Member member) {
// 아래 코드에서 작성된 메서드 호출 후 실행
List<Folder> folders = folderRepository.findByKeyword(query, member);
return folders.stream().map(FolderSearchResDto::new).collect(Collectors.toList());
}
}
'Spring' 카테고리의 다른 글
ExceptionHandler / ControllerAdvice 사용법 (0) | 2022.11.03 |
---|---|
WebSocket / STOMP (1) | 2022.10.28 |
Spring. Filter/Interceptor (0) | 2022.10.13 |
Spring. 영속성이란 (persistence) (0) | 2022.10.13 |
Spring. JPA ORM 및 연관관계 (0) | 2022.10.13 |
댓글