Skip to content

Commit

Permalink
Merge pull request #112 from Team-Umbba/refactor/#108-querydsl-optimi…
Browse files Browse the repository at this point in the history
…zation

[REFACTOR] Querydsl을 이용한 쿼리 최적화
  • Loading branch information
jun02160 authored Oct 24, 2023
2 parents 12b5856 + 3817b62 commit b5e4fcb
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 87 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ build/
!**/src/main/**/build/
!**/src/test/**/build/

## Querydsl
umbba-domain/src/main/generated

### STS ###
.apt_generated
.classpath
Expand Down
4 changes: 4 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,14 @@ subprojects {
apply plugin: "org.springframework.boot"
apply plugin: "io.spring.dependency-management"


sourceCompatibility = "11"

repositories {
mavenCentral()
maven {
url "https://plugins.gradle.org/m2/"
}
}

configurations {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import lombok.Builder;
import lombok.Getter;
import lombok.*;
import sopt.org.umbba.domain.domain.user.User;

import javax.validation.constraints.NotBlank;
Expand All @@ -12,6 +11,8 @@
@Getter
@Builder
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class UserInfoDto {

private Long userId;
Expand Down
37 changes: 19 additions & 18 deletions umbba-domain/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,25 @@ dependencies {
implementation group: "io.jsonwebtoken", name: "jjwt-jackson", version: "0.11.2"

// querydsl
// implementation "com.querydsl:querydsl-jpa"
// implementation "com.querydsl:querydsl-core"
// annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties["querydsl.version"]}:jpa"
// annotationProcessor "jakarta.persistence:jakarta.persistence-api:2.2.3"
// annotationProcessor "jakarta.annotation:jakarta.annotation-api:1.3.5"
implementation "com.querydsl:querydsl-jpa"
implementation "com.querydsl:querydsl-core"
implementation "com.querydsl:querydsl-collections"
annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jpa" // querydsl JPAAnnotationProcessor 사용 지정
annotationProcessor "jakarta.annotation:jakarta.annotation-api" // java.lang.NoClassDefFoundError (javax.annotation.Generated) 대응 코드
annotationProcessor "jakarta.persistence:jakarta.persistence-api" // java.lang.NoClassDefFoundError (javax.annotation.Entity) 대응 코드

}

def queryDslDir = "build/querydsl/generated"

sourceSets {
main.java.srcDirs += [queryDslDir]
}

//def queryDslDir = "build/querydsl/generated"
//
//sourceSets {
// main.java.srcDirs += [queryDslDir]
//}
//
//tasks.withType(JavaCompile) {
// options.annotationProcessorGeneratedSourcesDirectory = file(queryDslDir)
//}
//
//clean.doLast {
// file(queryDslDir).deleteDir()
//}
tasks.withType(JavaCompile) {
options.getGeneratedSourceOutputDirectory().set(file(queryDslDir))
}

clean.doLast {
file(queryDslDir).deleteDir()
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,27 @@
package sopt.org.umbba.domain.config.jpa;

import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import sopt.org.umbba.domain.UmbbaDomainRoot;

import com.querydsl.jpa.impl.JPAQueryFactory;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@Configuration
@EntityScan(basePackageClasses = {UmbbaDomainRoot.class})
@EnableJpaRepositories(basePackageClasses = {UmbbaDomainRoot.class})
@EnableJpaAuditing
public class JpaConfig {

@PersistenceContext
private EntityManager em;
@Bean
public JPAQueryFactory jpaQueryFactory() {
return new JPAQueryFactory(em);
}
}
Original file line number Diff line number Diff line change
@@ -1,78 +1,75 @@
package sopt.org.umbba.domain.domain.parentchild.dao;

import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.querydsl.jpa.JPAExpressions;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;
import sopt.org.umbba.domain.domain.parentchild.Parentchild;
import sopt.org.umbba.domain.domain.user.QUser;
import sopt.org.umbba.domain.domain.user.User;

import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import static sopt.org.umbba.domain.domain.parentchild.QParentchild.parentchild;
import static sopt.org.umbba.domain.domain.user.QUser.user;

@Slf4j
@Repository
@RequiredArgsConstructor
public class ParentchildDao {

@PersistenceContext
private EntityManager em;

private final JPAQueryFactory queryFactory;

public Optional<Parentchild> findByUserId(Long userId) {

String jpql = "SELECT pc FROM Parentchild pc " +
"JOIN User u ON u.parentChild = pc " +
"WHERE u.id = :id";
return Optional.ofNullable(queryFactory
.selectFrom(parentchild)
.leftJoin(user.parentChild, parentchild)
.where(
userIdEq(userId)
)
.fetchOne());
}

try {
Parentchild parentchild = em.createQuery(jpql, Parentchild.class)
.setParameter("id", userId)
.getSingleResult();
return Optional.ofNullable(parentchild);
public Optional<User> findMatchUserByUserId(Long userId) {

} catch (NoResultException e) {
return Optional.empty();
} finally {
em.close();
}
QUser uc = new QUser("uc");

return Optional.ofNullable(queryFactory
.select(user)
.from(user)
.join(uc).on(uc.parentChild.eq(user.parentChild))
.where(uc.id.eq(userId).and(uc.id.ne(user.id)))
.fetchOne());
}

public Optional<User> findMatchUserByUserId(Long userId) {
public List<String> findFcmTokensById(Long parentchildId) {

String jpql = "SELECT u FROM User u " +
"JOIN User uc ON uc.parentChild = u.parentChild " +
"WHERE uc.id = :id AND uc.id != u.id";

try {
User user = em.createQuery(jpql, User.class)
.setParameter("id", userId)
.getSingleResult();
return Optional.ofNullable(user);
} catch (NoResultException e) {
return Optional.empty();
} finally {
em.close();
}
return queryFactory
.select(user.fcmToken)
.from(user)
.leftJoin(user.parentChild, parentchild)
.where(
parentchildIdEq(parentchildId)
)
.fetch();
}

public List<String> findFcmTokensById(Long parentchildId) {

String jpql = "SELECT u.fcmToken FROM User u " +
"JOIN Parentchild pc ON pc.id = u.parentChild.id " +
"WHERE pc.id = :id";

try {
return em.createQuery(jpql, String.class)
.setParameter("id", parentchildId)
.getResultList();
} catch (NoResultException e) {
return new ArrayList<>();
} finally {
em.close();
}
private BooleanExpression userIdEq(Long userId) {
return userId != null ? user.id.eq(userId) : null;
}

private BooleanExpression parentchildIdEq(Long parentchildId) {
return parentchildId != null ? parentchild.id.eq(parentchildId) : null;
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package sopt.org.umbba.domain.domain.qna.dao;

import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;
import sopt.org.umbba.domain.domain.qna.QnA;
Expand All @@ -11,40 +14,34 @@
import java.util.List;
import java.util.Optional;

import static sopt.org.umbba.domain.domain.parentchild.QParentchild.parentchild;
import static sopt.org.umbba.domain.domain.user.QUser.user;

@Slf4j
@Repository
@RequiredArgsConstructor
public class QnADao {

@PersistenceContext
private EntityManager em;

private final JPAQueryFactory queryFactory;


// READ

// 유저 아이디로 QnA 리스트 조회하기
public Optional<List<QnA>> findQnASByUserId(Long userId) {
log.info("jpql 실행 전");
String jpql = "SELECT q FROM Parentchild pc " +
"JOIN pc.qnaList q " +
"LEFT JOIN User u ON u.parentChild.id = pc.id " +
"WHERE u.id = :id";

try {
TypedQuery<QnA> query = em.createQuery(jpql, QnA.class);

log.info("query 실행 성공: {}", query);
List<QnA> qnaList = query
.setParameter("id", userId)
.getResultList();
log.info("query 실행 결과: {}", qnaList.toString());

return Optional.of(qnaList);
} catch (NoResultException e) {

return Optional.empty();
} finally {
em.close();
}
public List<QnA> findQnASByUserId(Long userId) {
return queryFactory
.select(parentchild.qnaList)
.from(parentchild)
.leftJoin(user.parentChild, parentchild)
.where(userIdEq(userId))
.fetchOne();
}

private BooleanExpression userIdEq(Long userId) {
return userId != null ? user.id.eq(userId) : null;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ public void schedulePushAlarm(String cronExpression, Long parentchildId) {

scheduledFuture = taskScheduler.schedule(() -> {


try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Expand Down

0 comments on commit b5e4fcb

Please sign in to comment.