diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..27c5368 Binary files /dev/null and b/.DS_Store differ diff --git a/build.gradle b/build.gradle index 2abdc6f..a307817 100644 --- a/build.gradle +++ b/build.gradle @@ -1,33 +1,58 @@ plugins { - id 'java' - id 'org.springframework.boot' version '3.3.5' - id 'io.spring.dependency-management' version '1.1.6' + id 'java' + id 'org.springframework.boot' version '3.2.3' + id 'io.spring.dependency-management' version '1.1.6' } -group = 'java-lab' +group = 'com.umc' version = '0.0.1-SNAPSHOT' java { - toolchain { - languageVersion = JavaLanguageVersion.of(17) - } + toolchain { + languageVersion = JavaLanguageVersion.of(17) + } } repositories { - mavenCentral() + mavenCentral() +} + +configurations { + compileOnly { + extendsFrom annotationProcessor + } } dependencies { - implementation 'org.springframework.boot:spring-boot-starter' - implementation 'org.springframework.boot:spring-boot-starter-web' - implementation 'org.springframework.boot:spring-boot-starter-data-jpa' - implementation 'org.projectlombok:lombok' - implementation 'org.springframework.boot:spring-boot-starter-validation' - testImplementation 'org.springframework.boot:spring-boot-starter-test' - runtimeOnly 'com.mysql:mysql-connector-j' - testRuntimeOnly 'org.junit.platform:junit-platform-launcher' + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-validation' + compileOnly 'org.projectlombok:lombok' + runtimeOnly 'com.mysql:mysql-connector-j' + annotationProcessor 'org.projectlombok:lombok' + + // 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" + + testImplementation 'org.springframework.boot:spring-boot-starter-test' // Spring Boot Test + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.2' // JUnit 5 API + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.9.2' // JUnit 5 엔진 + +} + +def generated = 'src/main/generated' // Q 클래스 생성 경로 설정 + +sourceSets { + main { + java { + srcDirs = ['src/main/java', 'src/main/resources'] + } + } } tasks.named('test') { - useJUnitPlatform() + useJUnitPlatform() } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index a4b76b9..943f0cb 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index df97d72..f398c33 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip networkTimeout=10000 -validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index f5feea6..65dcd68 100755 --- a/gradlew +++ b/gradlew @@ -15,8 +15,6 @@ # See the License for the specific language governing permissions and # limitations under the License. # -# SPDX-License-Identifier: Apache-2.0 -# ############################################################################## # @@ -57,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -85,9 +83,10 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s -' "$PWD" ) || exit +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -134,13 +133,10 @@ location of your Java installation." fi else JAVACMD=java - if ! command -v java >/dev/null 2>&1 - then - die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." - fi fi # Increase the maximum file descriptors if we can. @@ -148,7 +144,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 + # shellcheck disable=SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -156,7 +152,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 + # shellcheck disable=SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -201,15 +197,11 @@ if "$cygwin" || "$msys" ; then done fi - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, -# and any embedded shellness will be escaped. -# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be -# treated as '${Hostname}' itself on the command line. +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ diff --git a/gradlew.bat b/gradlew.bat index 9d21a21..93e3f59 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -13,8 +13,6 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem -@rem SPDX-License-Identifier: Apache-2.0 -@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## @@ -45,11 +43,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. 1>&2 -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. goto fail @@ -59,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. 1>&2 -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. goto fail diff --git a/src/.DS_Store b/src/.DS_Store new file mode 100644 index 0000000..03e1870 Binary files /dev/null and b/src/.DS_Store differ diff --git a/src/main/generated/umc/study/domain/QCategory.java b/src/main/generated/umc/study/domain/QCategory.java new file mode 100644 index 0000000..74e9d7c --- /dev/null +++ b/src/main/generated/umc/study/domain/QCategory.java @@ -0,0 +1,47 @@ +package umc.study.domain; + +import static com.querydsl.core.types.PathMetadataFactory.*; + +import com.querydsl.core.types.dsl.*; + +import com.querydsl.core.types.PathMetadata; +import javax.annotation.processing.Generated; +import com.querydsl.core.types.Path; + + +/** + * QCategory is a Querydsl query type for Category + */ +@Generated("com.querydsl.codegen.DefaultEntitySerializer") +public class QCategory extends EntityPathBase { + + private static final long serialVersionUID = -673748992L; + + public static final QCategory category = new QCategory("category"); + + public final umc.study.domain.common.QBaseEntity _super = new umc.study.domain.common.QBaseEntity(this); + + //inherited + public final DateTimePath createdAt = _super.createdAt; + + public final NumberPath id = createNumber("id", Long.class); + + public final StringPath name = createString("name"); + + //inherited + public final DateTimePath updatedAt = _super.updatedAt; + + public QCategory(String variable) { + super(Category.class, forVariable(variable)); + } + + public QCategory(Path path) { + super(path.getType(), path.getMetadata()); + } + + public QCategory(PathMetadata metadata) { + super(Category.class, metadata); + } + +} + diff --git a/src/main/generated/umc/study/domain/QMember.java b/src/main/generated/umc/study/domain/QMember.java new file mode 100644 index 0000000..e562b6f --- /dev/null +++ b/src/main/generated/umc/study/domain/QMember.java @@ -0,0 +1,68 @@ +package umc.study.domain; + +import static com.querydsl.core.types.PathMetadataFactory.*; + +import com.querydsl.core.types.dsl.*; + +import com.querydsl.core.types.PathMetadata; +import javax.annotation.processing.Generated; +import com.querydsl.core.types.Path; +import com.querydsl.core.types.dsl.PathInits; + + +/** + * QMember is a Querydsl query type for Member + */ +@Generated("com.querydsl.codegen.DefaultEntitySerializer") +public class QMember extends EntityPathBase { + + private static final long serialVersionUID = 543821340L; + + public static final QMember member = new QMember("member1"); + + public final umc.study.domain.common.QBaseEntity _super = new umc.study.domain.common.QBaseEntity(this); + + public final DateTimePath birth = createDateTime("birth", java.time.LocalDateTime.class); + + //inherited + public final DateTimePath createdAt = _super.createdAt; + + public final StringPath email = createString("email"); + + public final NumberPath foodCategory = createNumber("foodCategory", Long.class); + + public final EnumPath gender = createEnum("gender", umc.study.domain.enums.Gender.class); + + public final NumberPath id = createNumber("id", Long.class); + + public final ListPath memberAgreeList = this.createList("memberAgreeList", umc.study.domain.mapping.MemberAgree.class, umc.study.domain.mapping.QMemberAgree.class, PathInits.DIRECT2); + + public final ListPath memberMissionList = this.createList("memberMissionList", umc.study.domain.mapping.MemberMission.class, umc.study.domain.mapping.QMemberMission.class, PathInits.DIRECT2); + + public final ListPath memberPreferList = this.createList("memberPreferList", umc.study.domain.mapping.MemberPrefer.class, umc.study.domain.mapping.QMemberPrefer.class, PathInits.DIRECT2); + + public final StringPath name = createString("name"); + + public final StringPath phoneNumber = createString("phoneNumber"); + + public final ListPath reviewList = this.createList("reviewList", Review.class, QReview.class, PathInits.DIRECT2); + + public final EnumPath socialType = createEnum("socialType", umc.study.domain.enums.SocialType.class); + + //inherited + public final DateTimePath updatedAt = _super.updatedAt; + + public QMember(String variable) { + super(Member.class, forVariable(variable)); + } + + public QMember(Path path) { + super(path.getType(), path.getMetadata()); + } + + public QMember(PathMetadata metadata) { + super(Member.class, metadata); + } + +} + diff --git a/src/main/generated/umc/study/domain/QMission.java b/src/main/generated/umc/study/domain/QMission.java new file mode 100644 index 0000000..624fd48 --- /dev/null +++ b/src/main/generated/umc/study/domain/QMission.java @@ -0,0 +1,65 @@ +package umc.study.domain; + +import static com.querydsl.core.types.PathMetadataFactory.*; + +import com.querydsl.core.types.dsl.*; + +import com.querydsl.core.types.PathMetadata; +import javax.annotation.processing.Generated; +import com.querydsl.core.types.Path; +import com.querydsl.core.types.dsl.PathInits; + + +/** + * QMission is a Querydsl query type for Mission + */ +@Generated("com.querydsl.codegen.DefaultEntitySerializer") +public class QMission extends EntityPathBase { + + private static final long serialVersionUID = -200839606L; + + private static final PathInits INITS = PathInits.DIRECT2; + + public static final QMission mission = new QMission("mission"); + + public final umc.study.domain.common.QBaseEntity _super = new umc.study.domain.common.QBaseEntity(this); + + //inherited + public final DateTimePath createdAt = _super.createdAt; + + public final NumberPath id = createNumber("id", Long.class); + + public final StringPath missionSpec = createString("missionSpec"); + + public final StringPath name = createString("name"); + + public final NumberPath reward = createNumber("reward", Long.class); + + public final QStore storeId; + + //inherited + public final DateTimePath updatedAt = _super.updatedAt; + + public QMission(String variable) { + this(Mission.class, forVariable(variable), INITS); + } + + public QMission(Path path) { + this(path.getType(), path.getMetadata(), PathInits.getFor(path.getMetadata(), INITS)); + } + + public QMission(PathMetadata metadata) { + this(metadata, PathInits.getFor(metadata, INITS)); + } + + public QMission(PathMetadata metadata, PathInits inits) { + this(Mission.class, metadata, inits); + } + + public QMission(Class type, PathMetadata metadata, PathInits inits) { + super(type, metadata, inits); + this.storeId = inits.isInitialized("storeId") ? new QStore(forProperty("storeId"), inits.get("storeId")) : null; + } + +} + diff --git a/src/main/generated/umc/study/domain/QRegion.java b/src/main/generated/umc/study/domain/QRegion.java new file mode 100644 index 0000000..d325b68 --- /dev/null +++ b/src/main/generated/umc/study/domain/QRegion.java @@ -0,0 +1,47 @@ +package umc.study.domain; + +import static com.querydsl.core.types.PathMetadataFactory.*; + +import com.querydsl.core.types.dsl.*; + +import com.querydsl.core.types.PathMetadata; +import javax.annotation.processing.Generated; +import com.querydsl.core.types.Path; + + +/** + * QRegion is a Querydsl query type for Region + */ +@Generated("com.querydsl.codegen.DefaultEntitySerializer") +public class QRegion extends EntityPathBase { + + private static final long serialVersionUID = 686795382L; + + public static final QRegion region = new QRegion("region"); + + public final umc.study.domain.common.QBaseEntity _super = new umc.study.domain.common.QBaseEntity(this); + + //inherited + public final DateTimePath createdAt = _super.createdAt; + + public final NumberPath id = createNumber("id", Long.class); + + public final StringPath name = createString("name"); + + //inherited + public final DateTimePath updatedAt = _super.updatedAt; + + public QRegion(String variable) { + super(Region.class, forVariable(variable)); + } + + public QRegion(Path path) { + super(path.getType(), path.getMetadata()); + } + + public QRegion(PathMetadata metadata) { + super(Region.class, metadata); + } + +} + diff --git a/src/main/generated/umc/study/domain/QReview.java b/src/main/generated/umc/study/domain/QReview.java new file mode 100644 index 0000000..65a3f18 --- /dev/null +++ b/src/main/generated/umc/study/domain/QReview.java @@ -0,0 +1,68 @@ +package umc.study.domain; + +import static com.querydsl.core.types.PathMetadataFactory.*; + +import com.querydsl.core.types.dsl.*; + +import com.querydsl.core.types.PathMetadata; +import javax.annotation.processing.Generated; +import com.querydsl.core.types.Path; +import com.querydsl.core.types.dsl.PathInits; + + +/** + * QReview is a Querydsl query type for Review + */ +@Generated("com.querydsl.codegen.DefaultEntitySerializer") +public class QReview extends EntityPathBase { + + private static final long serialVersionUID = 687241946L; + + private static final PathInits INITS = PathInits.DIRECT2; + + public static final QReview review = new QReview("review"); + + public final umc.study.domain.common.QBaseEntity _super = new umc.study.domain.common.QBaseEntity(this); + + public final StringPath content = createString("content"); + + //inherited + public final DateTimePath createdAt = _super.createdAt; + + public final NumberPath id = createNumber("id", Long.class); + + public final QMember memberId; + + public final ListPath reviewImageList = this.createList("reviewImageList", ReviewImage.class, QReviewImage.class, PathInits.DIRECT2); + + public final NumberPath score = createNumber("score", Long.class); + + public final QStore storeId; + + //inherited + public final DateTimePath updatedAt = _super.updatedAt; + + public QReview(String variable) { + this(Review.class, forVariable(variable), INITS); + } + + public QReview(Path path) { + this(path.getType(), path.getMetadata(), PathInits.getFor(path.getMetadata(), INITS)); + } + + public QReview(PathMetadata metadata) { + this(metadata, PathInits.getFor(metadata, INITS)); + } + + public QReview(PathMetadata metadata, PathInits inits) { + this(Review.class, metadata, inits); + } + + public QReview(Class type, PathMetadata metadata, PathInits inits) { + super(type, metadata, inits); + this.memberId = inits.isInitialized("memberId") ? new QMember(forProperty("memberId")) : null; + this.storeId = inits.isInitialized("storeId") ? new QStore(forProperty("storeId"), inits.get("storeId")) : null; + } + +} + diff --git a/src/main/generated/umc/study/domain/QReviewImage.java b/src/main/generated/umc/study/domain/QReviewImage.java new file mode 100644 index 0000000..1f3db53 --- /dev/null +++ b/src/main/generated/umc/study/domain/QReviewImage.java @@ -0,0 +1,53 @@ +package umc.study.domain; + +import static com.querydsl.core.types.PathMetadataFactory.*; + +import com.querydsl.core.types.dsl.*; + +import com.querydsl.core.types.PathMetadata; +import javax.annotation.processing.Generated; +import com.querydsl.core.types.Path; +import com.querydsl.core.types.dsl.PathInits; + + +/** + * QReviewImage is a Querydsl query type for ReviewImage + */ +@Generated("com.querydsl.codegen.DefaultEntitySerializer") +public class QReviewImage extends EntityPathBase { + + private static final long serialVersionUID = -1472334175L; + + private static final PathInits INITS = PathInits.DIRECT2; + + public static final QReviewImage reviewImage = new QReviewImage("reviewImage"); + + public final NumberPath id = createNumber("id", Long.class); + + public final StringPath imageUrl = createString("imageUrl"); + + public final QReview reviewId; + + public QReviewImage(String variable) { + this(ReviewImage.class, forVariable(variable), INITS); + } + + public QReviewImage(Path path) { + this(path.getType(), path.getMetadata(), PathInits.getFor(path.getMetadata(), INITS)); + } + + public QReviewImage(PathMetadata metadata) { + this(metadata, PathInits.getFor(metadata, INITS)); + } + + public QReviewImage(PathMetadata metadata, PathInits inits) { + this(ReviewImage.class, metadata, inits); + } + + public QReviewImage(Class type, PathMetadata metadata, PathInits inits) { + super(type, metadata, inits); + this.reviewId = inits.isInitialized("reviewId") ? new QReview(forProperty("reviewId"), inits.get("reviewId")) : null; + } + +} + diff --git a/src/main/generated/umc/study/domain/QStore.java b/src/main/generated/umc/study/domain/QStore.java new file mode 100644 index 0000000..d7cb42c --- /dev/null +++ b/src/main/generated/umc/study/domain/QStore.java @@ -0,0 +1,65 @@ +package umc.study.domain; + +import static com.querydsl.core.types.PathMetadataFactory.*; + +import com.querydsl.core.types.dsl.*; + +import com.querydsl.core.types.PathMetadata; +import javax.annotation.processing.Generated; +import com.querydsl.core.types.Path; +import com.querydsl.core.types.dsl.PathInits; + + +/** + * QStore is a Querydsl query type for Store + */ +@Generated("com.querydsl.codegen.DefaultEntitySerializer") +public class QStore extends EntityPathBase { + + private static final long serialVersionUID = 1963195679L; + + private static final PathInits INITS = PathInits.DIRECT2; + + public static final QStore store = new QStore("store"); + + public final umc.study.domain.common.QBaseEntity _super = new umc.study.domain.common.QBaseEntity(this); + + public final StringPath address = createString("address"); + + //inherited + public final DateTimePath createdAt = _super.createdAt; + + public final NumberPath id = createNumber("id", Long.class); + + public final StringPath name = createString("name"); + + public final QRegion regionId; + + public final StringPath state = createString("state"); + + //inherited + public final DateTimePath updatedAt = _super.updatedAt; + + public QStore(String variable) { + this(Store.class, forVariable(variable), INITS); + } + + public QStore(Path path) { + this(path.getType(), path.getMetadata(), PathInits.getFor(path.getMetadata(), INITS)); + } + + public QStore(PathMetadata metadata) { + this(metadata, PathInits.getFor(metadata, INITS)); + } + + public QStore(PathMetadata metadata, PathInits inits) { + this(Store.class, metadata, inits); + } + + public QStore(Class type, PathMetadata metadata, PathInits inits) { + super(type, metadata, inits); + this.regionId = inits.isInitialized("regionId") ? new QRegion(forProperty("regionId")) : null; + } + +} + diff --git a/src/main/generated/umc/study/domain/QTerms.java b/src/main/generated/umc/study/domain/QTerms.java new file mode 100644 index 0000000..765354a --- /dev/null +++ b/src/main/generated/umc/study/domain/QTerms.java @@ -0,0 +1,51 @@ +package umc.study.domain; + +import static com.querydsl.core.types.PathMetadataFactory.*; + +import com.querydsl.core.types.dsl.*; + +import com.querydsl.core.types.PathMetadata; +import javax.annotation.processing.Generated; +import com.querydsl.core.types.Path; + + +/** + * QTerms is a Querydsl query type for Terms + */ +@Generated("com.querydsl.codegen.DefaultEntitySerializer") +public class QTerms extends EntityPathBase { + + private static final long serialVersionUID = 1963675077L; + + public static final QTerms terms = new QTerms("terms"); + + public final umc.study.domain.common.QBaseEntity _super = new umc.study.domain.common.QBaseEntity(this); + + public final StringPath body = createString("body"); + + //inherited + public final DateTimePath createdAt = _super.createdAt; + + public final NumberPath id = createNumber("id", Long.class); + + public final NumberPath optional = createNumber("optional", Integer.class); + + public final StringPath title = createString("title"); + + //inherited + public final DateTimePath updatedAt = _super.updatedAt; + + public QTerms(String variable) { + super(Terms.class, forVariable(variable)); + } + + public QTerms(Path path) { + super(path.getType(), path.getMetadata()); + } + + public QTerms(PathMetadata metadata) { + super(Terms.class, metadata); + } + +} + diff --git a/src/main/generated/umc/study/domain/common/QBaseEntity.java b/src/main/generated/umc/study/domain/common/QBaseEntity.java new file mode 100644 index 0000000..d7d2236 --- /dev/null +++ b/src/main/generated/umc/study/domain/common/QBaseEntity.java @@ -0,0 +1,39 @@ +package umc.study.domain.common; + +import static com.querydsl.core.types.PathMetadataFactory.*; + +import com.querydsl.core.types.dsl.*; + +import com.querydsl.core.types.PathMetadata; +import javax.annotation.processing.Generated; +import com.querydsl.core.types.Path; + + +/** + * QBaseEntity is a Querydsl query type for BaseEntity + */ +@Generated("com.querydsl.codegen.DefaultSupertypeSerializer") +public class QBaseEntity extends EntityPathBase { + + private static final long serialVersionUID = 2079264117L; + + public static final QBaseEntity baseEntity = new QBaseEntity("baseEntity"); + + public final DateTimePath createdAt = createDateTime("createdAt", java.time.LocalDateTime.class); + + public final DateTimePath updatedAt = createDateTime("updatedAt", java.time.LocalDateTime.class); + + public QBaseEntity(String variable) { + super(BaseEntity.class, forVariable(variable)); + } + + public QBaseEntity(Path path) { + super(path.getType(), path.getMetadata()); + } + + public QBaseEntity(PathMetadata metadata) { + super(BaseEntity.class, metadata); + } + +} + diff --git a/src/main/generated/umc/study/domain/mapping/QMemberAgree.java b/src/main/generated/umc/study/domain/mapping/QMemberAgree.java new file mode 100644 index 0000000..d71e5c6 --- /dev/null +++ b/src/main/generated/umc/study/domain/mapping/QMemberAgree.java @@ -0,0 +1,62 @@ +package umc.study.domain.mapping; + +import static com.querydsl.core.types.PathMetadataFactory.*; + +import com.querydsl.core.types.dsl.*; + +import com.querydsl.core.types.PathMetadata; +import javax.annotation.processing.Generated; +import com.querydsl.core.types.Path; +import com.querydsl.core.types.dsl.PathInits; + + +/** + * QMemberAgree is a Querydsl query type for MemberAgree + */ +@Generated("com.querydsl.codegen.DefaultEntitySerializer") +public class QMemberAgree extends EntityPathBase { + + private static final long serialVersionUID = 150024912L; + + private static final PathInits INITS = PathInits.DIRECT2; + + public static final QMemberAgree memberAgree = new QMemberAgree("memberAgree"); + + public final umc.study.domain.common.QBaseEntity _super = new umc.study.domain.common.QBaseEntity(this); + + //inherited + public final DateTimePath createdAt = _super.createdAt; + + public final NumberPath id = createNumber("id", Long.class); + + public final umc.study.domain.QMember memberId; + + public final umc.study.domain.QTerms termsId; + + //inherited + public final DateTimePath updatedAt = _super.updatedAt; + + public QMemberAgree(String variable) { + this(MemberAgree.class, forVariable(variable), INITS); + } + + public QMemberAgree(Path path) { + this(path.getType(), path.getMetadata(), PathInits.getFor(path.getMetadata(), INITS)); + } + + public QMemberAgree(PathMetadata metadata) { + this(metadata, PathInits.getFor(metadata, INITS)); + } + + public QMemberAgree(PathMetadata metadata, PathInits inits) { + this(MemberAgree.class, metadata, inits); + } + + public QMemberAgree(Class type, PathMetadata metadata, PathInits inits) { + super(type, metadata, inits); + this.memberId = inits.isInitialized("memberId") ? new umc.study.domain.QMember(forProperty("memberId")) : null; + this.termsId = inits.isInitialized("termsId") ? new umc.study.domain.QTerms(forProperty("termsId")) : null; + } + +} + diff --git a/src/main/generated/umc/study/domain/mapping/QMemberMission.java b/src/main/generated/umc/study/domain/mapping/QMemberMission.java new file mode 100644 index 0000000..53d9956 --- /dev/null +++ b/src/main/generated/umc/study/domain/mapping/QMemberMission.java @@ -0,0 +1,64 @@ +package umc.study.domain.mapping; + +import static com.querydsl.core.types.PathMetadataFactory.*; + +import com.querydsl.core.types.dsl.*; + +import com.querydsl.core.types.PathMetadata; +import javax.annotation.processing.Generated; +import com.querydsl.core.types.Path; +import com.querydsl.core.types.dsl.PathInits; + + +/** + * QMemberMission is a Querydsl query type for MemberMission + */ +@Generated("com.querydsl.codegen.DefaultEntitySerializer") +public class QMemberMission extends EntityPathBase { + + private static final long serialVersionUID = 263768240L; + + private static final PathInits INITS = PathInits.DIRECT2; + + public static final QMemberMission memberMission = new QMemberMission("memberMission"); + + public final umc.study.domain.common.QBaseEntity _super = new umc.study.domain.common.QBaseEntity(this); + + //inherited + public final DateTimePath createdAt = _super.createdAt; + + public final NumberPath id = createNumber("id", Long.class); + + public final umc.study.domain.QMember memberId; + + public final umc.study.domain.QMission missionId; + + public final EnumPath status = createEnum("status", umc.study.domain.enums.MissionStatus.class); + + //inherited + public final DateTimePath updatedAt = _super.updatedAt; + + public QMemberMission(String variable) { + this(MemberMission.class, forVariable(variable), INITS); + } + + public QMemberMission(Path path) { + this(path.getType(), path.getMetadata(), PathInits.getFor(path.getMetadata(), INITS)); + } + + public QMemberMission(PathMetadata metadata) { + this(metadata, PathInits.getFor(metadata, INITS)); + } + + public QMemberMission(PathMetadata metadata, PathInits inits) { + this(MemberMission.class, metadata, inits); + } + + public QMemberMission(Class type, PathMetadata metadata, PathInits inits) { + super(type, metadata, inits); + this.memberId = inits.isInitialized("memberId") ? new umc.study.domain.QMember(forProperty("memberId")) : null; + this.missionId = inits.isInitialized("missionId") ? new umc.study.domain.QMission(forProperty("missionId"), inits.get("missionId")) : null; + } + +} + diff --git a/src/main/generated/umc/study/domain/mapping/QMemberPrefer.java b/src/main/generated/umc/study/domain/mapping/QMemberPrefer.java new file mode 100644 index 0000000..0b69e3f --- /dev/null +++ b/src/main/generated/umc/study/domain/mapping/QMemberPrefer.java @@ -0,0 +1,62 @@ +package umc.study.domain.mapping; + +import static com.querydsl.core.types.PathMetadataFactory.*; + +import com.querydsl.core.types.dsl.*; + +import com.querydsl.core.types.PathMetadata; +import javax.annotation.processing.Generated; +import com.querydsl.core.types.Path; +import com.querydsl.core.types.dsl.PathInits; + + +/** + * QMemberPrefer is a Querydsl query type for MemberPrefer + */ +@Generated("com.querydsl.codegen.DefaultEntitySerializer") +public class QMemberPrefer extends EntityPathBase { + + private static final long serialVersionUID = 795014764L; + + private static final PathInits INITS = PathInits.DIRECT2; + + public static final QMemberPrefer memberPrefer = new QMemberPrefer("memberPrefer"); + + public final umc.study.domain.common.QBaseEntity _super = new umc.study.domain.common.QBaseEntity(this); + + public final umc.study.domain.QCategory categoryId; + + //inherited + public final DateTimePath createdAt = _super.createdAt; + + public final NumberPath id = createNumber("id", Long.class); + + public final umc.study.domain.QMember memberId; + + //inherited + public final DateTimePath updatedAt = _super.updatedAt; + + public QMemberPrefer(String variable) { + this(MemberPrefer.class, forVariable(variable), INITS); + } + + public QMemberPrefer(Path path) { + this(path.getType(), path.getMetadata(), PathInits.getFor(path.getMetadata(), INITS)); + } + + public QMemberPrefer(PathMetadata metadata) { + this(metadata, PathInits.getFor(metadata, INITS)); + } + + public QMemberPrefer(PathMetadata metadata, PathInits inits) { + this(MemberPrefer.class, metadata, inits); + } + + public QMemberPrefer(Class type, PathMetadata metadata, PathInits inits) { + super(type, metadata, inits); + this.categoryId = inits.isInitialized("categoryId") ? new umc.study.domain.QCategory(forProperty("categoryId")) : null; + this.memberId = inits.isInitialized("memberId") ? new umc.study.domain.QMember(forProperty("memberId")) : null; + } + +} + diff --git a/src/main/java/javalab/umc7th_mission/Umc7thMissionApplication.java b/src/main/java/javalab/umc7th_mission/Umc7thMissionApplication.java deleted file mode 100644 index e0dd79f..0000000 --- a/src/main/java/javalab/umc7th_mission/Umc7thMissionApplication.java +++ /dev/null @@ -1,13 +0,0 @@ -package javalab.umc7th_mission; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class Umc7thMissionApplication { - - public static void main(String[] args) { - SpringApplication.run(Umc7thMissionApplication.class, args); - } - -} diff --git a/src/main/java/umc/study/QueryDSLConfig.java b/src/main/java/umc/study/QueryDSLConfig.java new file mode 100644 index 0000000..d37c12a --- /dev/null +++ b/src/main/java/umc/study/QueryDSLConfig.java @@ -0,0 +1,18 @@ +package umc.study; + +import com.querydsl.jpa.impl.JPAQueryFactory; +import jakarta.persistence.EntityManager; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@RequiredArgsConstructor +public class QueryDSLConfig { + private final EntityManager entityManager; + + @Bean + public JPAQueryFactory jpaQueryFactory(){ + return new JPAQueryFactory(entityManager); + } +} diff --git a/src/main/java/umc/study/Umc7thMissionApplication.java b/src/main/java/umc/study/Umc7thMissionApplication.java new file mode 100644 index 0000000..a15aaf6 --- /dev/null +++ b/src/main/java/umc/study/Umc7thMissionApplication.java @@ -0,0 +1,63 @@ +package umc.study; + +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; +import umc.study.domain.Review; +import umc.study.service.MemberMissionService.MemberMissionQueryService; +import umc.study.service.MemberService.MemberQueryService; +import umc.study.service.MissionService.MissionQueryService; +import umc.study.service.ReviewService.ReviewQueryService; +import umc.study.service.StoreService.StoreQueryService; + +import java.util.List; + +@SpringBootApplication +@EnableJpaAuditing +public class Umc7thMissionApplication { + + public static void main(String[] args) { + + SpringApplication.run(Umc7thMissionApplication.class, args); + } + @Bean + public CommandLineRunner run(ApplicationContext context) { + return args -> { + StoreQueryService storeService = context.getBean(StoreQueryService.class); + MemberMissionQueryService memberMissionService = context.getBean(MemberMissionQueryService.class); + ReviewQueryService reviewService = context.getBean(ReviewQueryService.class); + MissionQueryService missionService = context.getBean(MissionQueryService.class); + MemberQueryService memberService = context.getBean(MemberQueryService.class); + + String name = "한우곱창"; + Long memberId = 2L; + Long storeId = 7L; + Long regionId = 1L; + Long userId = 1L; + +// System.out.println("Executing findStoresByNameAndScore with parameters:"); +// System.out.println("Name: " + name); +// storeService.findStoresByName(name).forEach(System.out::println); +// +// System.out.println("Executing findMemberMissionsByStoreId with parameters:"); +// System.out.println("MemberId: " + memberId); +// memberMissionService.findMemberMissionsByMemberId(memberId).forEach(System.out::println); +// +// System.out.println("Executing findReviewsByStoreId with parameters:"); +// System.out.println("StoreId: " + storeId); +// System.out.println("MemberId: " + memberId); +// reviewService.findReviewByMemberIdAndStoreId(storeId,memberId).forEach(System.out::println); +// +// System.out.println("Executing findMissionsWithCompletedCountByRegion with parameters:"); +// System.out.println("RegionId: " + regionId); +// missionService.findMissionsWithCompletedCountByRegion(regionId).forEach(System.out::println); + + System.out.println("Executing findMemberDetailsById with parameters:"); + System.out.println("UserId: " + userId); + memberService.findMemberByMemberDetailsId(userId).forEach(System.out::println); + }; + } +} diff --git a/src/main/java/umc/study/apiPayload/ApiResponse.java b/src/main/java/umc/study/apiPayload/ApiResponse.java new file mode 100644 index 0000000..5db2eac --- /dev/null +++ b/src/main/java/umc/study/apiPayload/ApiResponse.java @@ -0,0 +1,39 @@ +package umc.study.apiPayload; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import lombok.AllArgsConstructor; +import lombok.Getter; +import umc.study.apiPayload.code.BaseCode; +import umc.study.apiPayload.code.status.SuccessStatus; + +@Getter +@AllArgsConstructor +@JsonPropertyOrder({"isSuccess", "code", "message", "result"}) +public class ApiResponse { + + @JsonProperty("isSuccess") + private final Boolean isSuccess; + private final String code; + private final String message; + @JsonInclude(JsonInclude.Include.NON_NULL) + private T result; + + + // 성공한 경우 응답 생성 + + public static ApiResponse onSuccess(T result){ + return new ApiResponse<>(true, SuccessStatus._OK.getCode() , SuccessStatus._OK.getMessage(), result); + } + + public static ApiResponse of(BaseCode code, T result){ + return new ApiResponse<>(true, code.getReasonHttpStatus().getCode() , code.getReasonHttpStatus().getMessage(), result); + } + + + // 실패한 경우 응답 생성 + public static ApiResponse onFailure(String code, String message, T data){ + return new ApiResponse<>(false, code, message, data); + } +} diff --git a/src/main/java/umc/study/apiPayload/code/BaseCode.java b/src/main/java/umc/study/apiPayload/code/BaseCode.java new file mode 100644 index 0000000..3c3dd87 --- /dev/null +++ b/src/main/java/umc/study/apiPayload/code/BaseCode.java @@ -0,0 +1,8 @@ +package umc.study.apiPayload.code; + +public interface BaseCode { + + ReasonDTO getReason(); + + ReasonDTO getReasonHttpStatus(); +} diff --git a/src/main/java/umc/study/apiPayload/code/BaseErrorCode.java b/src/main/java/umc/study/apiPayload/code/BaseErrorCode.java new file mode 100644 index 0000000..b3fa13e --- /dev/null +++ b/src/main/java/umc/study/apiPayload/code/BaseErrorCode.java @@ -0,0 +1,7 @@ +package umc.study.apiPayload.code; + +public interface BaseErrorCode { + ErrorReasonDTO getReason(); + + ErrorReasonDTO getReasonHttpStatus(); +} diff --git a/src/main/java/umc/study/apiPayload/code/ErrorReasonDTO.java b/src/main/java/umc/study/apiPayload/code/ErrorReasonDTO.java new file mode 100644 index 0000000..f790186 --- /dev/null +++ b/src/main/java/umc/study/apiPayload/code/ErrorReasonDTO.java @@ -0,0 +1,17 @@ +package umc.study.apiPayload.code; + +import lombok.Builder; +import lombok.Getter; +import org.springframework.http.HttpStatus; + +@Getter +@Builder +public class ErrorReasonDTO { + private HttpStatus httpStatus; + + private final boolean isSuccess; + private final String code; + private final String message; + + public boolean getIsSuccess(){return isSuccess;} +} diff --git a/src/main/java/umc/study/apiPayload/code/ReasonDTO.java b/src/main/java/umc/study/apiPayload/code/ReasonDTO.java new file mode 100644 index 0000000..64f8b5e --- /dev/null +++ b/src/main/java/umc/study/apiPayload/code/ReasonDTO.java @@ -0,0 +1,17 @@ +package umc.study.apiPayload.code; + +import lombok.Builder; +import lombok.Getter; +import org.springframework.http.HttpStatus; + +@Getter +@Builder +public class ReasonDTO { + private HttpStatus httpStatus; + + private final boolean isSuccess; + private final String code; + private final String message; + + public boolean getIsSuccess(){return isSuccess;} +} diff --git a/src/main/java/umc/study/apiPayload/code/status/ErrorStatus.java b/src/main/java/umc/study/apiPayload/code/status/ErrorStatus.java new file mode 100644 index 0000000..a0912ce --- /dev/null +++ b/src/main/java/umc/study/apiPayload/code/status/ErrorStatus.java @@ -0,0 +1,49 @@ +package umc.study.apiPayload.code.status; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.springframework.http.HttpStatus; +import umc.study.apiPayload.code.BaseErrorCode; +import umc.study.apiPayload.code.ErrorReasonDTO; + +@Getter +@AllArgsConstructor +public enum ErrorStatus implements BaseErrorCode { + // 가장 일반적인 응답 + _INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "COMMON500", "서버 에러, 관리자에게 문의 바랍니다."), + _BAD_REQUEST(HttpStatus.BAD_REQUEST,"COMMON400","잘못된 요청입니다."), + _UNAUTHORIZED(HttpStatus.UNAUTHORIZED,"COMMON401","인증이 필요합니다."), + _FORBIDDEN(HttpStatus.FORBIDDEN, "COMMON403", "금지된 요청입니다."), + + + // 멤버 관려 에러 + MEMBER_NOT_FOUND(HttpStatus.BAD_REQUEST, "MEMBER4001", "사용자가 없습니다."), + NICKNAME_NOT_EXIST(HttpStatus.BAD_REQUEST, "MEMBER4002", "닉네임은 필수 입니다."), + + // 예시,,, + TEMP_EXCEPTION(HttpStatus.BAD_REQUEST, "TEMP4001","이거는 테스트"), + ARTICLE_NOT_FOUND(HttpStatus.NOT_FOUND, "ARTICLE4001", "게시글이 없습니다."); + + private final HttpStatus httpStatus; + private final String code; + private final String message; + + @Override + public ErrorReasonDTO getReason() { + return ErrorReasonDTO.builder() + .message(message) + .code(code) + .isSuccess(false) + .build(); + } + + @Override + public ErrorReasonDTO getReasonHttpStatus() { + return ErrorReasonDTO.builder() + .message(message) + .code(code) + .isSuccess(false) + .httpStatus(httpStatus) + .build(); + } +} diff --git a/src/main/java/umc/study/apiPayload/code/status/SuccessStatus.java b/src/main/java/umc/study/apiPayload/code/status/SuccessStatus.java new file mode 100644 index 0000000..3eb4812 --- /dev/null +++ b/src/main/java/umc/study/apiPayload/code/status/SuccessStatus.java @@ -0,0 +1,39 @@ +package umc.study.apiPayload.code.status; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.springframework.http.HttpStatus; +import umc.study.apiPayload.code.BaseCode; +import umc.study.apiPayload.code.ReasonDTO; + +@Getter +@AllArgsConstructor +public enum SuccessStatus implements BaseCode { + + // 일반적인 응답 + _OK(HttpStatus.OK, "COMMON200", "성공입니다."); + + private final HttpStatus httpStatus; + private final String code; + private final String message; + + @Override + public ReasonDTO getReason() { + return ReasonDTO.builder() + .message(message) + .code(code) + .isSuccess(true) + .build(); + } + + @Override + public ReasonDTO getReasonHttpStatus() { + return ReasonDTO.builder() + .message(message) + .code(code) + .isSuccess(true) + .httpStatus(httpStatus) + .build() + ; + } +} diff --git a/src/main/java/umc/study/apiPayload/exception/ExceptionAdvice.java b/src/main/java/umc/study/apiPayload/exception/ExceptionAdvice.java new file mode 100644 index 0000000..79b7ef5 --- /dev/null +++ b/src/main/java/umc/study/apiPayload/exception/ExceptionAdvice.java @@ -0,0 +1,119 @@ +package umc.study.apiPayload.exception; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.validation.ConstraintViolationException; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.context.request.ServletWebRequest; +import org.springframework.web.context.request.WebRequest; +import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; +import umc.study.apiPayload.ApiResponse; +import umc.study.apiPayload.code.ErrorReasonDTO; +import umc.study.apiPayload.code.status.ErrorStatus; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Optional; + +@Slf4j +@RestControllerAdvice(annotations = {RestController.class}) +public class ExceptionAdvice extends ResponseEntityExceptionHandler { + + + @ExceptionHandler + public ResponseEntity validation(ConstraintViolationException e, WebRequest request) { + String errorMessage = e.getConstraintViolations().stream() + .map(constraintViolation -> constraintViolation.getMessage()) + .findFirst() + .orElseThrow(() -> new RuntimeException("ConstraintViolationException 추출 도중 에러 발생")); + + return handleExceptionInternalConstraint(e, ErrorStatus.valueOf(errorMessage), HttpHeaders.EMPTY,request); + } + @Override + public ResponseEntity handleMethodArgumentNotValid(MethodArgumentNotValidException e, HttpHeaders headers, HttpStatusCode status, WebRequest request) { + + Map errors = new LinkedHashMap<>(); + + e.getBindingResult().getFieldErrors().stream() + .forEach(fieldError -> { + String fieldName = fieldError.getField(); + String errorMessage = Optional.ofNullable(fieldError.getDefaultMessage()).orElse(""); + errors.merge(fieldName, errorMessage, (existingErrorMessage, newErrorMessage) -> existingErrorMessage + ", " + newErrorMessage); + }); + + return handleExceptionInternalArgs(e,HttpHeaders.EMPTY,ErrorStatus.valueOf("_BAD_REQUEST"),request,errors); + } + + @ExceptionHandler + public ResponseEntity exception(Exception e, WebRequest request) { + e.printStackTrace(); + + return handleExceptionInternalFalse(e, ErrorStatus._INTERNAL_SERVER_ERROR, HttpHeaders.EMPTY, ErrorStatus._INTERNAL_SERVER_ERROR.getHttpStatus(),request, e.getMessage()); + } + + @ExceptionHandler(value = GeneralException.class) + public ResponseEntity onThrowException(GeneralException generalException, HttpServletRequest request) { + // GeneralException에 대해 다시 한번 오버로딩 된 함수를 호출 + ErrorReasonDTO errorReasonHttpStatus = generalException.getErrorReasonHttpStatus(); + return handleExceptionInternal(generalException,errorReasonHttpStatus,null,request); + } + + private ResponseEntity handleExceptionInternal(Exception e, ErrorReasonDTO reason, + HttpHeaders headers, HttpServletRequest request) { + // 상속받은 부모 클래스의 생성자를 호출 + ApiResponse body = ApiResponse.onFailure(reason.getCode(),reason.getMessage(),null); +// e.printStackTrace(); + + WebRequest webRequest = new ServletWebRequest(request); + return super.handleExceptionInternal( + e, + body, + headers, + reason.getHttpStatus(), + webRequest + ); + } + + private ResponseEntity handleExceptionInternalFalse(Exception e, ErrorStatus errorCommonStatus, + HttpHeaders headers, HttpStatus status, WebRequest request, String errorPoint) { + ApiResponse body = ApiResponse.onFailure(errorCommonStatus.getCode(),errorCommonStatus.getMessage(),errorPoint); + return super.handleExceptionInternal( + e, + body, + headers, + status, + request + ); + } + + private ResponseEntity handleExceptionInternalArgs(Exception e, HttpHeaders headers, ErrorStatus errorCommonStatus, + WebRequest request, Map errorArgs) { + ApiResponse body = ApiResponse.onFailure(errorCommonStatus.getCode(),errorCommonStatus.getMessage(),errorArgs); + return super.handleExceptionInternal( + e, + body, + headers, + errorCommonStatus.getHttpStatus(), + request + ); + } + + private ResponseEntity handleExceptionInternalConstraint(Exception e, ErrorStatus errorCommonStatus, + HttpHeaders headers, WebRequest request) { + ApiResponse body = ApiResponse.onFailure(errorCommonStatus.getCode(), errorCommonStatus.getMessage(), null); + return super.handleExceptionInternal( + e, + body, + headers, + errorCommonStatus.getHttpStatus(), + request + ); + } +} diff --git a/src/main/java/umc/study/apiPayload/exception/GeneralException.java b/src/main/java/umc/study/apiPayload/exception/GeneralException.java new file mode 100644 index 0000000..b59824c --- /dev/null +++ b/src/main/java/umc/study/apiPayload/exception/GeneralException.java @@ -0,0 +1,20 @@ +package umc.study.apiPayload.exception; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import umc.study.apiPayload.code.BaseErrorCode; +import umc.study.apiPayload.code.ErrorReasonDTO; + +@Getter +@AllArgsConstructor +public class GeneralException extends RuntimeException { + private BaseErrorCode code; + + public ErrorReasonDTO getErrorReason() { + return this.code.getReason(); + } + + public ErrorReasonDTO getErrorReasonHttpStatus(){ + return this.code.getReasonHttpStatus(); + } +} diff --git a/src/main/java/umc/study/apiPayload/exception/handler/TempHandler.java b/src/main/java/umc/study/apiPayload/exception/handler/TempHandler.java new file mode 100644 index 0000000..c0a4275 --- /dev/null +++ b/src/main/java/umc/study/apiPayload/exception/handler/TempHandler.java @@ -0,0 +1,10 @@ +package umc.study.apiPayload.exception.handler; + +import umc.study.apiPayload.code.BaseErrorCode; +import umc.study.apiPayload.exception.GeneralException; + +public class TempHandler extends GeneralException { + public TempHandler(BaseErrorCode errorCode){ + super(errorCode); // 상위클래스의 생성자를 호출하여, GeneralException의 로직대로 errorCode를 초기화 + } +} diff --git a/src/main/java/umc/study/converter/TempConverter.java b/src/main/java/umc/study/converter/TempConverter.java new file mode 100644 index 0000000..2e65642 --- /dev/null +++ b/src/main/java/umc/study/converter/TempConverter.java @@ -0,0 +1,16 @@ +package umc.study.converter; + +import umc.study.web.dto.TempResponse; + +public class TempConverter { + public static TempResponse.TempTestDTO toTempTestDTO() { + return TempResponse.TempTestDTO.builder() + .testString("This is Test!") + .build(); + } + public static TempResponse.TempExceptionDTO toTempExceptionDTO(Integer flag) { + return TempResponse.TempExceptionDTO.builder() + .flag(flag) + .build(); + } +} \ No newline at end of file diff --git a/src/main/java/umc/study/domain/Category.java b/src/main/java/umc/study/domain/Category.java new file mode 100644 index 0000000..dcd35bb --- /dev/null +++ b/src/main/java/umc/study/domain/Category.java @@ -0,0 +1,19 @@ +package umc.study.domain; + +import jakarta.persistence.*; +import lombok.*; +import umc.study.domain.common.BaseEntity; + +@Entity +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class Category extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(length = 20, nullable = false) + private String name; +} diff --git a/src/main/java/umc/study/domain/Member.java b/src/main/java/umc/study/domain/Member.java new file mode 100644 index 0000000..d4edd2a --- /dev/null +++ b/src/main/java/umc/study/domain/Member.java @@ -0,0 +1,83 @@ +package umc.study.domain; + +import jakarta.persistence.*; +import lombok.*; +import umc.study.domain.common.BaseEntity; +import umc.study.domain.enums.Gender; +import umc.study.domain.enums.SocialType; +import umc.study.domain.mapping.MemberAgree; +import umc.study.domain.mapping.MemberMission; +import umc.study.domain.mapping.MemberPrefer; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + + +@Entity +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class Member extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = false, columnDefinition = "VARCHAR(50)") + private String name; + + @Enumerated(EnumType.STRING) + private Gender gender; + + @Enumerated(EnumType.STRING) + private SocialType socialType; + + private LocalDateTime birth; + private Long foodCategory; + private String email; + private String phoneNumber; + + @OneToMany(mappedBy = "memberId", cascade = CascadeType.ALL) + private List reviewList = new ArrayList<>(); + + @OneToMany(mappedBy = "memberId", cascade = CascadeType.ALL) + private List memberMissionList = new ArrayList<>(); + + @OneToMany(mappedBy = "memberId", cascade = CascadeType.ALL) + private List memberPreferList = new ArrayList<>(); + + @OneToMany(mappedBy = "memberId", cascade = CascadeType.ALL) + private List memberAgreeList = new ArrayList<>(); + + @Override + public String toString() { + return "Member{" + + "id=" + id + + ", name='" + name + '\'' + + ", gender=" + gender + + ", socialType=" + socialType + + ", birth=" + birth + + ", foodCategory=" + foodCategory + + ", email='" + email + '\'' + + ", phoneNumber='" + phoneNumber + '\'' + + '}'; + } + + // @Builder 어노테이션과 명시적 생성자 사용 + @Builder + public Member(Gender gender, SocialType socialType, String name, LocalDateTime birth, Long foodCategory, + String email, String phoneNumber, List reviewList, List memberMissionList, + List memberPreferList, List memberAgreeList) { + this.gender = gender; + this.socialType = socialType; + this.name = name; + this.birth = birth; + this.foodCategory = foodCategory; + this.email = email; + this.phoneNumber = phoneNumber; + this.reviewList = reviewList != null ? reviewList : new ArrayList<>(); + this.memberMissionList = memberMissionList != null ? memberMissionList : new ArrayList<>(); + this.memberPreferList = memberPreferList != null ? memberPreferList : new ArrayList<>(); + this.memberAgreeList = memberAgreeList != null ? memberAgreeList : new ArrayList<>(); + } +} diff --git a/src/main/java/umc/study/domain/Mission.java b/src/main/java/umc/study/domain/Mission.java new file mode 100644 index 0000000..849649f --- /dev/null +++ b/src/main/java/umc/study/domain/Mission.java @@ -0,0 +1,49 @@ +package umc.study.domain; + +import jakarta.persistence.*; +import lombok.*; +import umc.study.domain.common.BaseEntity; + +@Entity +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PUBLIC) +@AllArgsConstructor +public class Mission extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(length = 50, nullable = false) + private String name; + + private String missionSpec; + + private Long reward; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "store_id", referencedColumnName = "id") + private Store storeId; + + public Mission(Long id, String name, String missionSpec, Long reward, Long completedMissionsCount) { + this.id = id; + this.name = name; + this.missionSpec = missionSpec; + this.reward = reward; + this.completedMissionsCount = completedMissionsCount; + } + + + @Transient + private Long completedMissionsCount; + + @Override + public String toString() { + return "Mission{" + + "reward=" + reward + + ", missionSpec='" + missionSpec + '\'' + + ", name='" + name + '\'' + + ", id=" + id + + '}'; + } +} diff --git a/src/main/java/umc/study/domain/Region.java b/src/main/java/umc/study/domain/Region.java new file mode 100644 index 0000000..2a75fbc --- /dev/null +++ b/src/main/java/umc/study/domain/Region.java @@ -0,0 +1,19 @@ +package umc.study.domain; + +import jakarta.persistence.*; +import lombok.*; +import umc.study.domain.common.BaseEntity; + +@Entity +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class Region extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(columnDefinition = "VARCHAR(50)", nullable = false) + private String name; +} diff --git a/src/main/java/umc/study/domain/Review.java b/src/main/java/umc/study/domain/Review.java new file mode 100644 index 0000000..9989331 --- /dev/null +++ b/src/main/java/umc/study/domain/Review.java @@ -0,0 +1,51 @@ +package umc.study.domain; + +import jakarta.persistence.*; +import lombok.*; +import umc.study.domain.common.BaseEntity; + +import java.util.ArrayList; +import java.util.List; + +@Entity +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class Review extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "member_id", referencedColumnName = "id") + private Member memberId; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "store_id", referencedColumnName = "id") + private Store storeId; + + private Long score; + private String content; + + @OneToMany(mappedBy = "reviewId", cascade = CascadeType.ALL) + private List reviewImageList = new ArrayList<>(); + + @Override + public String toString() { + return "Review{" + + "id=" + id + + ", score=" + score + + ", content='" + content + '\'' + + ", reviewImageList=" + reviewImageList + + '}'; + } + + @Builder + public Review(Member memberId, Store storeId, Long score, String content, List reviewImageList) { + this.memberId = memberId; + this.storeId = storeId; + this.score = score; + this.content = content; + this.reviewImageList = reviewImageList != null ? reviewImageList : new ArrayList<>(); + } +} diff --git a/src/main/java/umc/study/domain/ReviewImage.java b/src/main/java/umc/study/domain/ReviewImage.java new file mode 100644 index 0000000..84c5fdd --- /dev/null +++ b/src/main/java/umc/study/domain/ReviewImage.java @@ -0,0 +1,21 @@ +package umc.study.domain; + +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class ReviewImage { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) // JPA가 통신을 하는 DBMS의 방식을 따른다. + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) // 지연 로딩 -> 6주차 내용 + @JoinColumn(name = "review_id", referencedColumnName = "id") + private Review reviewId; + + private String imageUrl; +} diff --git a/src/main/java/umc/study/domain/Store.java b/src/main/java/umc/study/domain/Store.java new file mode 100644 index 0000000..9c0d714 --- /dev/null +++ b/src/main/java/umc/study/domain/Store.java @@ -0,0 +1,38 @@ +package umc.study.domain; + +import jakarta.persistence.*; +import lombok.*; +import umc.study.domain.common.BaseEntity; + +@Entity +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class Store extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(columnDefinition = "VARCHAR(50)", nullable = false) + private String name; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "region_id", referencedColumnName = "id") + private Region regionId; + + @Column(columnDefinition = "VARCHAR(50)", nullable = false) + private String address; + + @Column(columnDefinition = "VARCHAR(50)", nullable = false) + private String state; + + @Override + public String toString() { + return "Store{" + + "id=" + id + + ", name='" + name + '\'' + + ", address='" + address + '\'' + + '}'; + } +} diff --git a/src/main/java/umc/study/domain/Terms.java b/src/main/java/umc/study/domain/Terms.java new file mode 100644 index 0000000..cbd9ae2 --- /dev/null +++ b/src/main/java/umc/study/domain/Terms.java @@ -0,0 +1,23 @@ +package umc.study.domain; + +import jakarta.persistence.*; +import lombok.*; +import umc.study.domain.common.BaseEntity; + +@Entity +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class Terms extends BaseEntity{ + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(columnDefinition = "VARCHAR(20)", nullable = false) + private String title; + + private String body; + + private Integer optional; +} diff --git a/src/main/java/umc/study/domain/common/BaseEntity.java b/src/main/java/umc/study/domain/common/BaseEntity.java new file mode 100644 index 0000000..d048ee4 --- /dev/null +++ b/src/main/java/umc/study/domain/common/BaseEntity.java @@ -0,0 +1,21 @@ +package umc.study.domain.common; + +import jakarta.persistence.EntityListeners; +import jakarta.persistence.MappedSuperclass; +import lombok.Getter; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +import java.time.LocalDateTime; + +@MappedSuperclass +@EntityListeners(AuditingEntityListener.class) +@Getter +public class BaseEntity { + @CreatedDate + private LocalDateTime createdAt; + + @LastModifiedDate + private LocalDateTime updatedAt; +} diff --git a/src/main/java/umc/study/domain/enums/Gender.java b/src/main/java/umc/study/domain/enums/Gender.java new file mode 100644 index 0000000..e18be3b --- /dev/null +++ b/src/main/java/umc/study/domain/enums/Gender.java @@ -0,0 +1,6 @@ +package umc.study.domain.enums; + +public enum Gender { + // enum도 클래스 이므로 생성자를 두는 등의 방식이 가능 -> 6주차 에러 핸들링에서 + MALE, FEMALE +} diff --git a/src/main/java/umc/study/domain/enums/MissionStatus.java b/src/main/java/umc/study/domain/enums/MissionStatus.java new file mode 100644 index 0000000..ea8b3ca --- /dev/null +++ b/src/main/java/umc/study/domain/enums/MissionStatus.java @@ -0,0 +1,5 @@ +package umc.study.domain.enums; + +public enum MissionStatus { + NOT_STARTED, PROCEEDING, SUCCESS +} diff --git a/src/main/java/umc/study/domain/enums/SocialType.java b/src/main/java/umc/study/domain/enums/SocialType.java new file mode 100644 index 0000000..34c7e6c --- /dev/null +++ b/src/main/java/umc/study/domain/enums/SocialType.java @@ -0,0 +1,5 @@ +package umc.study.domain.enums; + +public enum SocialType { + KAKAO, GOOGLE, NAVER, APPLE +} diff --git a/src/main/java/umc/study/domain/mapping/MemberAgree.java b/src/main/java/umc/study/domain/mapping/MemberAgree.java new file mode 100644 index 0000000..1ec93ac --- /dev/null +++ b/src/main/java/umc/study/domain/mapping/MemberAgree.java @@ -0,0 +1,27 @@ +package umc.study.domain.mapping; + +import jakarta.persistence.*; +import lombok.*; +import umc.study.domain.Member; +import umc.study.domain.Terms; +import umc.study.domain.common.BaseEntity; + +@Entity +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class MemberAgree extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "member_id", referencedColumnName = "id") + private Member memberId; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "terms_id", referencedColumnName = "id") + private Terms termsId; +} diff --git a/src/main/java/umc/study/domain/mapping/MemberMission.java b/src/main/java/umc/study/domain/mapping/MemberMission.java new file mode 100644 index 0000000..7541252 --- /dev/null +++ b/src/main/java/umc/study/domain/mapping/MemberMission.java @@ -0,0 +1,43 @@ +package umc.study.domain.mapping; + +import jakarta.persistence.*; +import lombok.*; +import umc.study.domain.Member; +import umc.study.domain.Mission; +import umc.study.domain.common.BaseEntity; +import umc.study.domain.enums.MissionStatus; + +@Entity +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class MemberMission extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "member_id", referencedColumnName = "id") + private Member memberId; + + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "mission_id", referencedColumnName = "id") + private Mission missionId; + + @Override + public String toString() { + return "MemberMission{" + + "id=" + id + +// ", memberId=" + memberId + +// ", missionId=" + missionId + + ", status=" + status + + '}'; + } + + @Enumerated(EnumType.STRING) + @Column(columnDefinition = "VARCHAR(15) DEFAULT 'NOT_STARTED'") + private MissionStatus status; +} \ No newline at end of file diff --git a/src/main/java/umc/study/domain/mapping/MemberPrefer.java b/src/main/java/umc/study/domain/mapping/MemberPrefer.java new file mode 100644 index 0000000..149477a --- /dev/null +++ b/src/main/java/umc/study/domain/mapping/MemberPrefer.java @@ -0,0 +1,27 @@ +package umc.study.domain.mapping; + +import jakarta.persistence.*; +import lombok.*; +import umc.study.domain.Category; +import umc.study.domain.Member; +import umc.study.domain.common.BaseEntity; + +@Entity +@Getter +@Builder +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class MemberPrefer extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "member_id") + private Member memberId; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "category_id") + private Category categoryId; +} diff --git a/src/main/java/umc/study/repository/MemberMissionRepostiory/MemberMissionRepository.java b/src/main/java/umc/study/repository/MemberMissionRepostiory/MemberMissionRepository.java new file mode 100644 index 0000000..f8bab81 --- /dev/null +++ b/src/main/java/umc/study/repository/MemberMissionRepostiory/MemberMissionRepository.java @@ -0,0 +1,7 @@ +package umc.study.repository.MemberMissionRepostiory; + +import org.springframework.data.jpa.repository.JpaRepository; +import umc.study.domain.mapping.MemberMission; + +public interface MemberMissionRepository extends JpaRepository, MemberMissionRepositoryCustom { +} diff --git a/src/main/java/umc/study/repository/MemberMissionRepostiory/MemberMissionRepositoryCustom.java b/src/main/java/umc/study/repository/MemberMissionRepostiory/MemberMissionRepositoryCustom.java new file mode 100644 index 0000000..cee93bd --- /dev/null +++ b/src/main/java/umc/study/repository/MemberMissionRepostiory/MemberMissionRepositoryCustom.java @@ -0,0 +1,10 @@ +package umc.study.repository.MemberMissionRepostiory; + +import umc.study.domain.Member; +import umc.study.domain.mapping.MemberMission; + +import java.util.List; + +public interface MemberMissionRepositoryCustom { + List dynamicQueryWithBooleanBuilder(Long id); +} diff --git a/src/main/java/umc/study/repository/MemberMissionRepostiory/MemberMissionRepositoryImpl.java b/src/main/java/umc/study/repository/MemberMissionRepostiory/MemberMissionRepositoryImpl.java new file mode 100644 index 0000000..57f88dd --- /dev/null +++ b/src/main/java/umc/study/repository/MemberMissionRepostiory/MemberMissionRepositoryImpl.java @@ -0,0 +1,44 @@ +package umc.study.repository.MemberMissionRepostiory; + +import com.querydsl.core.BooleanBuilder; +import com.querydsl.jpa.impl.JPAQueryFactory; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Repository; +import umc.study.domain.Member; +import umc.study.domain.QMission; +import umc.study.domain.enums.MissionStatus; +import umc.study.domain.mapping.MemberMission; +import umc.study.domain.mapping.QMemberMission; + +import java.util.List; + +import static umc.study.domain.QMission.*; +import static umc.study.domain.mapping.QMemberMission.*; + +@Repository +@RequiredArgsConstructor +public class MemberMissionRepositoryImpl implements MemberMissionRepositoryCustom { + private final JPAQueryFactory jpaQueryFactory; + + @Override + public List dynamicQueryWithBooleanBuilder(Long memberId){ + BooleanBuilder predicate = new BooleanBuilder(); + + BooleanBuilder statusCondition = new BooleanBuilder(); + statusCondition.or(memberMission.status.eq(MissionStatus.PROCEEDING)) + .or(memberMission.status.eq(MissionStatus.SUCCESS)); + + + return jpaQueryFactory + .selectFrom(memberMission) + .join(memberMission.missionId, mission) // mission 테이블과의 조인 설정 + .where( + memberMission.memberId.id.eq(memberId) // memberId에 대한 조건 설정 + .and(statusCondition) // 상태 조건 설정 + ) + .orderBy(memberMission.status.desc()) // status에 대한 내림차순 정렬 + .limit(10) // limit 10 + .offset(0) // offset 0 + .fetch(); + } +} diff --git a/src/main/java/umc/study/repository/MemberRepository/MemberRepository.java b/src/main/java/umc/study/repository/MemberRepository/MemberRepository.java new file mode 100644 index 0000000..7f934cc --- /dev/null +++ b/src/main/java/umc/study/repository/MemberRepository/MemberRepository.java @@ -0,0 +1,7 @@ +package umc.study.repository.MemberRepository; + +import org.springframework.data.jpa.repository.JpaRepository; +import umc.study.domain.Member; + +public interface MemberRepository extends JpaRepository, MemberRepositoryCustom { +} diff --git a/src/main/java/umc/study/repository/MemberRepository/MemberRepositoryCustom.java b/src/main/java/umc/study/repository/MemberRepository/MemberRepositoryCustom.java new file mode 100644 index 0000000..406ea78 --- /dev/null +++ b/src/main/java/umc/study/repository/MemberRepository/MemberRepositoryCustom.java @@ -0,0 +1,7 @@ +package umc.study.repository.MemberRepository; + +import umc.study.domain.Member; + +public interface MemberRepositoryCustom { + Member findMemberDetailsById(Long userId); +} \ No newline at end of file diff --git a/src/main/java/umc/study/repository/MemberRepository/MemberRepositoryImpl.java b/src/main/java/umc/study/repository/MemberRepository/MemberRepositoryImpl.java new file mode 100644 index 0000000..1e2d977 --- /dev/null +++ b/src/main/java/umc/study/repository/MemberRepository/MemberRepositoryImpl.java @@ -0,0 +1,22 @@ +package umc.study.repository.MemberRepository; + +import com.querydsl.jpa.impl.JPAQueryFactory; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Repository; +import umc.study.domain.Member; + +import static umc.study.domain.QMember.member; + +@Repository +@RequiredArgsConstructor +public class MemberRepositoryImpl implements MemberRepositoryCustom { + private final JPAQueryFactory jpaQueryFactory; + + @Override + public Member findMemberDetailsById(Long userId) { + return jpaQueryFactory + .selectFrom(member) + .where(member.id.eq(userId)) + .fetchOne(); + } +} \ No newline at end of file diff --git a/src/main/java/umc/study/repository/MissionRepository/MissionRepository.java b/src/main/java/umc/study/repository/MissionRepository/MissionRepository.java new file mode 100644 index 0000000..1c85ba8 --- /dev/null +++ b/src/main/java/umc/study/repository/MissionRepository/MissionRepository.java @@ -0,0 +1,7 @@ +package umc.study.repository.MissionRepository; + +import org.springframework.data.jpa.repository.JpaRepository; +import umc.study.domain.Mission; + +public interface MissionRepository extends JpaRepository, MissionRepositoryCustom { +} diff --git a/src/main/java/umc/study/repository/MissionRepository/MissionRepositoryCustom.java b/src/main/java/umc/study/repository/MissionRepository/MissionRepositoryCustom.java new file mode 100644 index 0000000..f911e9e --- /dev/null +++ b/src/main/java/umc/study/repository/MissionRepository/MissionRepositoryCustom.java @@ -0,0 +1,8 @@ +package umc.study.repository.MissionRepository; + +import umc.study.domain.Mission; +import java.util.List; + +public interface MissionRepositoryCustom { + List findMissionsWithCompletedCountByRegion(Long regionId); +} diff --git a/src/main/java/umc/study/repository/MissionRepository/MissionRepositoryImpl.java b/src/main/java/umc/study/repository/MissionRepository/MissionRepositoryImpl.java new file mode 100644 index 0000000..d489ebe --- /dev/null +++ b/src/main/java/umc/study/repository/MissionRepository/MissionRepositoryImpl.java @@ -0,0 +1,44 @@ +package umc.study.repository.MissionRepository; + +import com.querydsl.core.types.Projections; +import com.querydsl.jpa.impl.JPAQueryFactory; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Repository; +import umc.study.domain.Mission; +import umc.study.domain.enums.MissionStatus; + +import java.util.List; + +import static umc.study.domain.QMission.mission; +import static umc.study.domain.QStore.store; +import static umc.study.domain.QRegion.region; +import static umc.study.domain.mapping.QMemberMission.memberMission; + + +@Repository +@RequiredArgsConstructor +public class MissionRepositoryImpl implements MissionRepositoryCustom { + + private final JPAQueryFactory jpaQueryFactory; + + @Override + public List findMissionsWithCompletedCountByRegion(Long regionId) { + return jpaQueryFactory + .select(Projections.fields(Mission.class, + mission.id, + mission.name, + mission.missionSpec, + mission.reward, + memberMission.id.count().as("completedMissionsCount") + )) + .from(mission) + .leftJoin(mission.storeId, store) + .leftJoin(store.regionId, region) + .leftJoin(memberMission).on(memberMission.missionId.id.eq(mission.id) + .and(memberMission.status.eq(MissionStatus.valueOf("SUCCESS")))) + .where(region.id.eq(regionId)) + .groupBy(mission.id, mission.name, mission.missionSpec, mission.reward) + .orderBy(mission.createdAt.desc()) + .fetch(); + } +} diff --git a/src/main/java/umc/study/repository/ReviewRepository/ReviewRepository.java b/src/main/java/umc/study/repository/ReviewRepository/ReviewRepository.java new file mode 100644 index 0000000..d60ee14 --- /dev/null +++ b/src/main/java/umc/study/repository/ReviewRepository/ReviewRepository.java @@ -0,0 +1,7 @@ +package umc.study.repository.ReviewRepository; + +import org.springframework.data.jpa.repository.JpaRepository; +import umc.study.domain.Review; + +public interface ReviewRepository extends JpaRepository, ReviewRepositoryCustom { +} diff --git a/src/main/java/umc/study/repository/ReviewRepository/ReviewRepositoryCustom.java b/src/main/java/umc/study/repository/ReviewRepository/ReviewRepositoryCustom.java new file mode 100644 index 0000000..c372984 --- /dev/null +++ b/src/main/java/umc/study/repository/ReviewRepository/ReviewRepositoryCustom.java @@ -0,0 +1,9 @@ +package umc.study.repository.ReviewRepository; + +import umc.study.domain.Review; + +import java.util.List; + +public interface ReviewRepositoryCustom { + List dynamicQueryWithBooleanBuilder(Long memberId, Long storeId); +} diff --git a/src/main/java/umc/study/repository/ReviewRepository/ReviewRepositoryImpl.java b/src/main/java/umc/study/repository/ReviewRepository/ReviewRepositoryImpl.java new file mode 100644 index 0000000..ebabf4e --- /dev/null +++ b/src/main/java/umc/study/repository/ReviewRepository/ReviewRepositoryImpl.java @@ -0,0 +1,44 @@ +package umc.study.repository.ReviewRepository; + +import com.querydsl.core.BooleanBuilder; +import com.querydsl.jpa.impl.JPAQueryFactory; +import jakarta.persistence.EntityManager; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Repository; +import umc.study.domain.Review; + +import java.util.List; + +import static umc.study.domain.QReview.review; +import static umc.study.domain.QMember.member; +import static umc.study.domain.QStore.store; + +@Repository +@RequiredArgsConstructor +public class ReviewRepositoryImpl implements ReviewRepositoryCustom { + private final JPAQueryFactory jpaQueryFactory; + private final EntityManager entityManager; + @Override + public List dynamicQueryWithBooleanBuilder(Long memberId, Long storeId) { + entityManager.clear(); // 1차 캐시 비우기 + BooleanBuilder predicate = new BooleanBuilder(); + + if (memberId != null) { + predicate.and(review.memberId.id.eq(memberId)); + } + if (storeId != null) { + predicate.and(review.storeId.id.eq(storeId)); + } + + return jpaQueryFactory + .selectFrom(review) + .join(review.memberId, member).fetchJoin() + .join(review.storeId, store).fetchJoin() + .leftJoin(review.reviewImageList).fetchJoin() // reviewImageList를 fetchJoin으로 로딩 + .where(predicate) + .orderBy(review.createdAt.desc()) + .fetch(); + + } + +} diff --git a/src/main/java/umc/study/repository/StoreRepository/StoreRepository.java b/src/main/java/umc/study/repository/StoreRepository/StoreRepository.java new file mode 100644 index 0000000..81cf3bf --- /dev/null +++ b/src/main/java/umc/study/repository/StoreRepository/StoreRepository.java @@ -0,0 +1,7 @@ +package umc.study.repository.StoreRepository; + +import org.springframework.data.jpa.repository.JpaRepository; +import umc.study.domain.Store; + +public interface StoreRepository extends JpaRepository, StoreRepositoryCustom { +} diff --git a/src/main/java/umc/study/repository/StoreRepository/StoreRepositoryCustom.java b/src/main/java/umc/study/repository/StoreRepository/StoreRepositoryCustom.java new file mode 100644 index 0000000..16447ec --- /dev/null +++ b/src/main/java/umc/study/repository/StoreRepository/StoreRepositoryCustom.java @@ -0,0 +1,10 @@ +package umc.study.repository.StoreRepository; + +import umc.study.domain.Store; + +import java.util.List; + + +public interface StoreRepositoryCustom { + List dynamicQueryWithBooleanBuilder(String name); +} \ No newline at end of file diff --git a/src/main/java/umc/study/repository/StoreRepository/StoreRepositoryImpl.java b/src/main/java/umc/study/repository/StoreRepository/StoreRepositoryImpl.java new file mode 100644 index 0000000..689f385 --- /dev/null +++ b/src/main/java/umc/study/repository/StoreRepository/StoreRepositoryImpl.java @@ -0,0 +1,31 @@ +package umc.study.repository.StoreRepository; + +import com.querydsl.core.BooleanBuilder; +import com.querydsl.jpa.impl.JPAQueryFactory; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Repository; +import umc.study.domain.QStore; +import umc.study.domain.Store; + +import java.util.List; + +@Repository +@RequiredArgsConstructor +public class StoreRepositoryImpl implements StoreRepositoryCustom{ + private final JPAQueryFactory jpaQueryFactory; + private final QStore store = QStore.store; + + @Override + public List dynamicQueryWithBooleanBuilder(String name) { + BooleanBuilder predicate = new BooleanBuilder(); + + if (name != null) { + predicate.and(store.name.eq(name)); + } + + return jpaQueryFactory + .selectFrom(store) + .where(predicate) + .fetch(); + } +} \ No newline at end of file diff --git a/src/main/java/umc/study/service/MemberMissionService/MemberMissionQueryService.java b/src/main/java/umc/study/service/MemberMissionService/MemberMissionQueryService.java new file mode 100644 index 0000000..c2cac65 --- /dev/null +++ b/src/main/java/umc/study/service/MemberMissionService/MemberMissionQueryService.java @@ -0,0 +1,11 @@ +package umc.study.service.MemberMissionService; + +import umc.study.domain.mapping.MemberMission; + +import java.util.List; + +public interface MemberMissionQueryService { + +// Optional findMemberMission(Long id); + List findMemberMissionsByMemberId(Long id); +} diff --git a/src/main/java/umc/study/service/MemberMissionService/MemberMissionQueryServiceImpl.java b/src/main/java/umc/study/service/MemberMissionService/MemberMissionQueryServiceImpl.java new file mode 100644 index 0000000..c9593c9 --- /dev/null +++ b/src/main/java/umc/study/service/MemberMissionService/MemberMissionQueryServiceImpl.java @@ -0,0 +1,27 @@ +package umc.study.service.MemberMissionService; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import umc.study.domain.Member; +import umc.study.domain.mapping.MemberMission; +import umc.study.repository.MemberMissionRepostiory.MemberMissionRepository; + +import java.util.List; + +@Service +public class MemberMissionQueryServiceImpl implements MemberMissionQueryService { + private MemberMissionRepository memberMissionRepository; + + @Autowired // 생성자 주입 방식 사용 + public MemberMissionQueryServiceImpl(MemberMissionRepository memberMissionRepository) { + this.memberMissionRepository = memberMissionRepository; + } + @Override + public List findMemberMissionsByMemberId(Long MemberId) { + List filteredMemberMissions = memberMissionRepository.dynamicQueryWithBooleanBuilder(MemberId); + + filteredMemberMissions.forEach(mission -> System.out.println("MemberMission: " + mission)); + + return filteredMemberMissions; + } +} diff --git a/src/main/java/umc/study/service/MemberService/MemberQueryService.java b/src/main/java/umc/study/service/MemberService/MemberQueryService.java new file mode 100644 index 0000000..5df27bf --- /dev/null +++ b/src/main/java/umc/study/service/MemberService/MemberQueryService.java @@ -0,0 +1,9 @@ +package umc.study.service.MemberService; + +import umc.study.domain.Member; + +import java.util.List; + +public interface MemberQueryService { + List findMemberByMemberDetailsId(Long memberId); +} diff --git a/src/main/java/umc/study/service/MemberService/MemberQueryServiceImpl.java b/src/main/java/umc/study/service/MemberService/MemberQueryServiceImpl.java new file mode 100644 index 0000000..ed1d00d --- /dev/null +++ b/src/main/java/umc/study/service/MemberService/MemberQueryServiceImpl.java @@ -0,0 +1,26 @@ +package umc.study.service.MemberService; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import umc.study.domain.Member; +import umc.study.repository.MemberRepository.MemberRepository; + +import java.util.List; + +// MemberQueryServiceImpl.java +@Service +@Transactional(readOnly = true) +public class MemberQueryServiceImpl implements MemberQueryService { + + private final MemberRepository memberRepository; + + public MemberQueryServiceImpl(MemberRepository memberRepository) { + this.memberRepository = memberRepository; + } + + @Override + public List findMemberByMemberDetailsId(Long userId) { + Member member = memberRepository.findMemberDetailsById(userId); + return member != null ? List.of(member) : List.of(); + } +} diff --git a/src/main/java/umc/study/service/MissionService/MissionQueryService.java b/src/main/java/umc/study/service/MissionService/MissionQueryService.java new file mode 100644 index 0000000..c5c8486 --- /dev/null +++ b/src/main/java/umc/study/service/MissionService/MissionQueryService.java @@ -0,0 +1,9 @@ +package umc.study.service.MissionService; + +import umc.study.domain.Mission; + +import java.util.List; + +public interface MissionQueryService { + List findMissionsWithCompletedCountByRegion(Long regionId); +} diff --git a/src/main/java/umc/study/service/MissionService/MissionQueryServiceImpl.java b/src/main/java/umc/study/service/MissionService/MissionQueryServiceImpl.java new file mode 100644 index 0000000..eed4230 --- /dev/null +++ b/src/main/java/umc/study/service/MissionService/MissionQueryServiceImpl.java @@ -0,0 +1,22 @@ +package umc.study.service.MissionService; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import umc.study.domain.Mission; +import umc.study.repository.MissionRepository.MissionRepository; + +import java.util.List; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class MissionQueryServiceImpl implements MissionQueryService { + + private final MissionRepository missionRepository; + + @Override + public List findMissionsWithCompletedCountByRegion(Long regionId) { + return missionRepository.findMissionsWithCompletedCountByRegion(regionId); + } +} diff --git a/src/main/java/umc/study/service/ReviewService/ReviewQueryService.java b/src/main/java/umc/study/service/ReviewService/ReviewQueryService.java new file mode 100644 index 0000000..efcb4d4 --- /dev/null +++ b/src/main/java/umc/study/service/ReviewService/ReviewQueryService.java @@ -0,0 +1,9 @@ +package umc.study.service.ReviewService; + +import umc.study.domain.Review; + +import java.util.List; + +public interface ReviewQueryService { + List findReviewByMemberIdAndStoreId(Long storeId, Long memberId); +} diff --git a/src/main/java/umc/study/service/ReviewService/ReviewQueryServiceImpl.java b/src/main/java/umc/study/service/ReviewService/ReviewQueryServiceImpl.java new file mode 100644 index 0000000..90aa625 --- /dev/null +++ b/src/main/java/umc/study/service/ReviewService/ReviewQueryServiceImpl.java @@ -0,0 +1,21 @@ +package umc.study.service.ReviewService; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import umc.study.domain.Review; +import umc.study.repository.ReviewRepository.ReviewRepository; + +import java.util.List; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) // 트랜잭션 추가 +public class ReviewQueryServiceImpl implements ReviewQueryService { + private final ReviewRepository reviewRepository; + + @Override + public List findReviewByMemberIdAndStoreId(Long storeId, Long memberId) { + return reviewRepository.dynamicQueryWithBooleanBuilder(memberId, storeId); + } +} diff --git a/src/main/java/umc/study/service/StoreService/StoreQueryService.java b/src/main/java/umc/study/service/StoreService/StoreQueryService.java new file mode 100644 index 0000000..4e15ea9 --- /dev/null +++ b/src/main/java/umc/study/service/StoreService/StoreQueryService.java @@ -0,0 +1,12 @@ +package umc.study.service.StoreService; + +import umc.study.domain.Store; + +import java.util.List; +import java.util.Optional; + +public interface StoreQueryService { + + Optional findStore(Long id); + List findStoresByName(String name); +} \ No newline at end of file diff --git a/src/main/java/umc/study/service/StoreService/StoreQueryServiceImpl.java b/src/main/java/umc/study/service/StoreService/StoreQueryServiceImpl.java new file mode 100644 index 0000000..e7df062 --- /dev/null +++ b/src/main/java/umc/study/service/StoreService/StoreQueryServiceImpl.java @@ -0,0 +1,32 @@ +package umc.study.service.StoreService; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import umc.study.domain.Store; +import umc.study.repository.StoreRepository.StoreRepository; + +import java.util.List; +import java.util.Optional; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class StoreQueryServiceImpl implements StoreQueryService{ + + private final StoreRepository storeRepository; + + @Override + public Optional findStore(Long id) { + return storeRepository.findById(id); + } + + @Override + public List findStoresByName(String name) { + List filteredStores = storeRepository.dynamicQueryWithBooleanBuilder(name); + + filteredStores.forEach(store -> System.out.println("Store: " + store)); + + return filteredStores; + } +} \ No newline at end of file diff --git a/src/main/java/umc/study/service/TempService/TempCommandService.java b/src/main/java/umc/study/service/TempService/TempCommandService.java new file mode 100644 index 0000000..43b4414 --- /dev/null +++ b/src/main/java/umc/study/service/TempService/TempCommandService.java @@ -0,0 +1,6 @@ +package umc.study.service.TempService; + +public interface TempCommandService { + // GET요청이 아닌 요청에 대햇너느 비즈니스 로직을 CommandService로 네이밍한다. + // 서비스를 만들 경우 인터페이스를 먼저 두고 이를 구체화한다 +} diff --git a/src/main/java/umc/study/service/TempService/TempCommandServiceImpl.java b/src/main/java/umc/study/service/TempService/TempCommandServiceImpl.java new file mode 100644 index 0000000..cda23ed --- /dev/null +++ b/src/main/java/umc/study/service/TempService/TempCommandServiceImpl.java @@ -0,0 +1,10 @@ +package umc.study.service.TempService; + +import lombok.NoArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@NoArgsConstructor +public class TempCommandServiceImpl implements TempCommandService { + // 컨트롤러는 인터페이스를 의존하며 실제 인터페이스에 대한 구체화 클래스는 스프링부트의 의존성 주입을 이용한다 +} diff --git a/src/main/java/umc/study/service/TempService/TempQueryService.java b/src/main/java/umc/study/service/TempService/TempQueryService.java new file mode 100644 index 0000000..251029d --- /dev/null +++ b/src/main/java/umc/study/service/TempService/TempQueryService.java @@ -0,0 +1,5 @@ +package umc.study.service.TempService; + +public interface TempQueryService { + void CheckFlag(Integer flag); +} diff --git a/src/main/java/umc/study/service/TempService/TempQueryServiceImpl.java b/src/main/java/umc/study/service/TempService/TempQueryServiceImpl.java new file mode 100644 index 0000000..2a0e232 --- /dev/null +++ b/src/main/java/umc/study/service/TempService/TempQueryServiceImpl.java @@ -0,0 +1,17 @@ +package umc.study.service.TempService; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import umc.study.apiPayload.code.status.ErrorStatus; +import umc.study.apiPayload.exception.handler.TempHandler; + +@Service +@RequiredArgsConstructor +public class TempQueryServiceImpl implements TempQueryService{ + // 컨트롤러는 인터페이스를 의존하며 실제 인터페이스에 대한 구체화 클래스는 스프링부트의 의존성 주입을 이용한다 + @Override + public void CheckFlag(Integer flag){ + if(flag == 1) //if문 내부로 들어오면 Service 이후 controller로 가지 않고, 바로 Exception handler에 의해 응답이 보내진다. + throw new TempHandler(ErrorStatus.TEMP_EXCEPTION); + } +} diff --git a/src/main/java/umc/study/web/controller/TempRestController.java b/src/main/java/umc/study/web/controller/TempRestController.java new file mode 100644 index 0000000..fa5af1c --- /dev/null +++ b/src/main/java/umc/study/web/controller/TempRestController.java @@ -0,0 +1,29 @@ +package umc.study.web.controller; + +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import umc.study.apiPayload.ApiResponse; +import umc.study.converter.TempConverter; +import umc.study.service.TempService.TempQueryService; +import umc.study.web.dto.TempResponse; + +@RestController +@RequestMapping("/temp") +@RequiredArgsConstructor +public class TempRestController { + private final TempQueryService tempQueryService; + + @GetMapping("/test") + public ApiResponse testAPI() { + + return ApiResponse.onSuccess(TempConverter.toTempTestDTO()); + } + @GetMapping("/exception") + public ApiResponse exceptionAPI(@RequestParam Integer flag) { + tempQueryService.CheckFlag(flag); + return ApiResponse.onSuccess(TempConverter.toTempExceptionDTO(flag)); + } +} \ No newline at end of file diff --git a/src/main/java/umc/study/web/dto/TempRequest.java b/src/main/java/umc/study/web/dto/TempRequest.java new file mode 100644 index 0000000..ae31723 --- /dev/null +++ b/src/main/java/umc/study/web/dto/TempRequest.java @@ -0,0 +1,4 @@ +package umc.study.web.dto; + +public class TempRequest { +} diff --git a/src/main/java/umc/study/web/dto/TempResponse.java b/src/main/java/umc/study/web/dto/TempResponse.java new file mode 100644 index 0000000..81bc6b0 --- /dev/null +++ b/src/main/java/umc/study/web/dto/TempResponse.java @@ -0,0 +1,25 @@ +package umc.study.web.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +public class TempResponse { + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class TempTestDTO{ + String testString; + } + + @Builder + @Getter + @NoArgsConstructor + @AllArgsConstructor + public static class TempExceptionDTO{ + Integer flag; + } +} \ No newline at end of file diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..ac11eca --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,19 @@ +spring: + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://localhost:3306/umc_study + username: root + password: sw051621!! + sql: # 데이터베이스 초기화 전략 지정 + init: + mode: never # DB 초기화 하지 않음(APP 실행 시 기존 DB 구조나 데이터에 대해 변경 X) + jpa: + properties: + hibernate: # DB와 상호작용을 위한 ORM 프레임워크 + dialect: org.hibernate.dialect.MySQL8Dialect # hibernate에서 SQL문을 생성할 때 사용할 DB 방언 지정 + show_sql: true # 실행되는 SQL문을 콘솔에 출력 + format_sql: true # SQL문을 가독성 있게 포맷해서 출력 + use_sql_comments: true # SQL 쿼리에 주석을 추가 + hbm2ddl: + auto: update # 데이터베이스 스키마 자동 생성 및 업데이트 전략 설정 + default_batch_fetch_size: 1000 # 배치 크기 \ No newline at end of file diff --git a/src/test/java/javalab/umc7th_mission/Umc7thMissionApplicationTests.java b/src/test/java/javalab/umc7th_mission/Umc7thMissionApplicationTests.java index a3f685a..5492192 100644 --- a/src/test/java/javalab/umc7th_mission/Umc7thMissionApplicationTests.java +++ b/src/test/java/javalab/umc7th_mission/Umc7thMissionApplicationTests.java @@ -1,13 +1,19 @@ package javalab.umc7th_mission; import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import umc.study.service.StoreService.StoreQueryService; @SpringBootTest class Umc7thMissionApplicationTests { + @Autowired + private StoreQueryService storeQueryService; // StoreQueryService 빈 주입 + @Test void contextLoads() { + // StoreQueryService가 정상적으로 주입되었는지 확인 + assert(storeQueryService != null); } - }