diff --git a/.gitignore b/.gitignore index 7b41cca0..8ab1ea93 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,9 @@ build/ !**/src/main/**/build/ !**/src/test/**/build/ +## Querydsl +umbba-domain/src/main/generated + ### STS ### .apt_generated .classpath diff --git a/build.gradle b/build.gradle index ba29e21c..d7a7395c 100644 --- a/build.gradle +++ b/build.gradle @@ -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 { diff --git a/umbba-api/src/main/java/sopt/org/umbba/api/controller/user/dto/request/UserInfoDto.java b/umbba-api/src/main/java/sopt/org/umbba/api/controller/user/dto/request/UserInfoDto.java index 9336b0b4..e3dddd6b 100644 --- a/umbba-api/src/main/java/sopt/org/umbba/api/controller/user/dto/request/UserInfoDto.java +++ b/umbba-api/src/main/java/sopt/org/umbba/api/controller/user/dto/request/UserInfoDto.java @@ -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; @@ -12,6 +11,8 @@ @Getter @Builder @JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class) +@NoArgsConstructor(access = AccessLevel.PRIVATE) +@AllArgsConstructor(access = AccessLevel.PRIVATE) public class UserInfoDto { private Long userId; diff --git a/umbba-domain/build.gradle b/umbba-domain/build.gradle index 5c44fbc2..9f7ba1b2 100644 --- a/umbba-domain/build.gradle +++ b/umbba-domain/build.gradle @@ -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() +} diff --git a/umbba-domain/src/main/java/sopt/org/umbba/domain/config/jpa/JpaConfig.java b/umbba-domain/src/main/java/sopt/org/umbba/domain/config/jpa/JpaConfig.java index 0e0ab3c6..20b49642 100644 --- a/umbba-domain/src/main/java/sopt/org/umbba/domain/config/jpa/JpaConfig.java +++ b/umbba-domain/src/main/java/sopt/org/umbba/domain/config/jpa/JpaConfig.java @@ -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); + } } diff --git a/umbba-domain/src/main/java/sopt/org/umbba/domain/domain/parentchild/dao/ParentchildDao.java b/umbba-domain/src/main/java/sopt/org/umbba/domain/domain/parentchild/dao/ParentchildDao.java index 40627f80..d0d47ab5 100644 --- a/umbba-domain/src/main/java/sopt/org/umbba/domain/domain/parentchild/dao/ParentchildDao.java +++ b/umbba-domain/src/main/java/sopt/org/umbba/domain/domain/parentchild/dao/ParentchildDao.java @@ -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 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 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 findMatchUserByUserId(Long userId) { + public List 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 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; + } } diff --git a/umbba-domain/src/main/java/sopt/org/umbba/domain/domain/qna/dao/QnADao.java b/umbba-domain/src/main/java/sopt/org/umbba/domain/domain/qna/dao/QnADao.java index febe6379..e7446aca 100644 --- a/umbba-domain/src/main/java/sopt/org/umbba/domain/domain/qna/dao/QnADao.java +++ b/umbba-domain/src/main/java/sopt/org/umbba/domain/domain/qna/dao/QnADao.java @@ -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; @@ -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> 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 query = em.createQuery(jpql, QnA.class); - - log.info("query 실행 성공: {}", query); - List 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 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; } } diff --git a/umbba-notification/src/main/java/sopt/org/umbba/notification/service/fcm/FCMService.java b/umbba-notification/src/main/java/sopt/org/umbba/notification/service/fcm/FCMService.java index 948fc1e4..52586d4b 100644 --- a/umbba-notification/src/main/java/sopt/org/umbba/notification/service/fcm/FCMService.java +++ b/umbba-notification/src/main/java/sopt/org/umbba/notification/service/fcm/FCMService.java @@ -184,6 +184,7 @@ public void schedulePushAlarm(String cronExpression, Long parentchildId) { scheduledFuture = taskScheduler.schedule(() -> { + try { Thread.sleep(1000); } catch (InterruptedException e) {