Initial commit
This commit is contained in:
15
backend/board-service/Dockerfile
Normal file
15
backend/board-service/Dockerfile
Normal file
@@ -0,0 +1,15 @@
|
||||
# openjdk8 base image
|
||||
FROM openjdk:8-jre-alpine
|
||||
|
||||
# config server uri: dockder run --e 로 변경 가능
|
||||
ENV SPRING_CLOUD_CONFIG_URI https://egov-config.paas-ta.org
|
||||
# jar 파일이 복사되는 위치
|
||||
ENV APP_HOME=/usr/app/
|
||||
# 작업 시작 위치
|
||||
WORKDIR $APP_HOME
|
||||
# jar 파일 복사
|
||||
COPY build/libs/*.jar app.jar
|
||||
# application port
|
||||
#EXPOSE 8000
|
||||
# 실행 (application-cf.yml 프로필이 기본값)
|
||||
CMD ["java", "-Dspring.profiles.active=${profile:cf}", "-jar", "app.jar"]
|
||||
98
backend/board-service/build.gradle
Normal file
98
backend/board-service/build.gradle
Normal file
@@ -0,0 +1,98 @@
|
||||
plugins {
|
||||
id 'org.springframework.boot' version '2.4.5'
|
||||
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
|
||||
// querydsl
|
||||
id 'com.ewerk.gradle.plugins.querydsl' version '1.0.10'
|
||||
id 'java'
|
||||
}
|
||||
|
||||
group = 'org.egovframe.cloud'
|
||||
version = '0.1'
|
||||
sourceCompatibility = '1.8'
|
||||
|
||||
configurations {
|
||||
compileOnly {
|
||||
extendsFrom annotationProcessor
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven { url "https://maven.egovframe.go.kr/maven/" } // egovframe maven 원격 저장소
|
||||
}
|
||||
|
||||
ext {
|
||||
set('springCloudVersion', "2020.0.3")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// implementation files('../../module-common/build/libs/module-common-0.1.jar') // 공통 모듈, @ComponentScan(basePackages={"org.egovframe.cloud"}) 추가해야 적용된다
|
||||
implementation 'org.egovframe.cloud:module-common:0.1'
|
||||
implementation('org.egovframe.rte:org.egovframe.rte.fdl.cmmn:4.0.0') {
|
||||
exclude group: 'org.egovframe.rte', module: 'org.egovframe.rte.fdl.logging'
|
||||
}
|
||||
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-security'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-validation'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-web'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-actuator'
|
||||
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
|
||||
implementation 'org.springframework.cloud:spring-cloud-starter-config' // config
|
||||
implementation 'org.springframework.cloud:spring-cloud-starter-bootstrap' // config
|
||||
implementation 'org.springframework.cloud:spring-cloud-starter-bus-amqp' // bus
|
||||
implementation 'org.springframework.cloud:spring-cloud-starter-sleuth'
|
||||
implementation 'org.springframework.cloud:spring-cloud-sleuth-zipkin'
|
||||
implementation 'net.logstash.logback:logstash-logback-encoder:6.6' // logstash logback
|
||||
implementation 'mysql:mysql-connector-java'
|
||||
implementation 'io.jsonwebtoken:jjwt:0.9.1'
|
||||
// querydsl
|
||||
implementation 'com.querydsl:querydsl-jpa'
|
||||
implementation 'com.querydsl:querydsl-sql:4.4.0'
|
||||
implementation 'com.querydsl:querydsl-sql-spring:4.4.0'
|
||||
|
||||
//messaging
|
||||
implementation 'org.springframework.cloud:spring-cloud-stream'
|
||||
implementation 'org.springframework.cloud:spring-cloud-stream-binder-rabbit'
|
||||
|
||||
// swagger
|
||||
implementation group: 'io.springfox', name: 'springfox-swagger2', version: '2.9.2'
|
||||
implementation group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.9.2'
|
||||
annotationProcessor "org.springframework.boot:spring-boot-configuration-processor"
|
||||
|
||||
// lombok
|
||||
implementation 'org.projectlombok:lombok'
|
||||
annotationProcessor 'org.projectlombok:lombok'
|
||||
testImplementation 'org.projectlombok:lombok'
|
||||
testAnnotationProcessor 'org.projectlombok:lombok'
|
||||
|
||||
testImplementation 'com.h2database:h2'
|
||||
testImplementation 'com.github.gavlyukovskiy:p6spy-spring-boot-starter:1.5.7' // 테스트시에만 출력
|
||||
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
||||
}
|
||||
|
||||
dependencyManagement {
|
||||
imports {
|
||||
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
|
||||
}
|
||||
}
|
||||
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
|
||||
// querydsl 추가 시작
|
||||
def querydslDir = "$buildDir/generated/querydsl"
|
||||
querydsl {
|
||||
jpa = true
|
||||
querydslSourcesDir = querydslDir
|
||||
}
|
||||
sourceSets {
|
||||
main.java.srcDir querydslDir
|
||||
}
|
||||
configurations {
|
||||
querydsl.extendsFrom compileClasspath
|
||||
}
|
||||
compileQuerydsl {
|
||||
options.annotationProcessorPath = configurations.querydsl
|
||||
}
|
||||
// querydsl 추가 끝
|
||||
185
backend/board-service/gradlew
vendored
Executable file
185
backend/board-service/gradlew
vendored
Executable file
@@ -0,0 +1,185 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
#
|
||||
# Copyright 2015 the original author or authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# 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"
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
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
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=`expr $i + 1`
|
||||
done
|
||||
case $i in
|
||||
0) set -- ;;
|
||||
1) set -- "$args0" ;;
|
||||
2) set -- "$args0" "$args1" ;;
|
||||
3) set -- "$args0" "$args1" "$args2" ;;
|
||||
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=`save "$@"`
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
89
backend/board-service/gradlew.bat
vendored
Normal file
89
backend/board-service/gradlew.bat
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto execute
|
||||
|
||||
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
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
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
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
16
backend/board-service/manifest.yml
Normal file
16
backend/board-service/manifest.yml
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
applications:
|
||||
- name: egov-board-service # CF push 시 생성되는 이름
|
||||
# memory: 512M # 메모리
|
||||
instances: 1 # 인스턴스 수
|
||||
host: egov-board-service # host 명으로 유일해야 함
|
||||
path: build/libs/board-service-0.1.jar # build 후 생성된 jar 위치
|
||||
buildpack: java_buildpack # cf buildpacks 명령어로 java buildpack 이름 확인
|
||||
services:
|
||||
- egov-discovery-provided-service # discovery service binding
|
||||
env:
|
||||
spring_profiles_active: cf
|
||||
spring_cloud_config_uri: https://egov-config.paas-ta.org
|
||||
app_name: egov-board-service # logstash custom app name
|
||||
TZ: Asia/Seoul
|
||||
JAVA_OPTS: -Xss349k
|
||||
1
backend/board-service/settings.gradle
Normal file
1
backend/board-service/settings.gradle
Normal file
@@ -0,0 +1 @@
|
||||
rootProject.name = 'board-service'
|
||||
@@ -0,0 +1,39 @@
|
||||
package org.egovframe.cloud.boardservice;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.domain.EntityScan;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.boardservice.BoardServiceApplication
|
||||
* <p>
|
||||
* 게시판 서비스 어플리케이션 클래스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/07/28
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/07/28 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@ComponentScan(basePackages={"org.egovframe.cloud.common", "org.egovframe.cloud.servlet", "org.egovframe.cloud.boardservice"}) // org.egovframe.cloud.common package 포함하기 위해
|
||||
@EntityScan({"org.egovframe.cloud.servlet.domain", "org.egovframe.cloud.boardservice.domain"})
|
||||
@SpringBootApplication
|
||||
public class BoardServiceApplication {
|
||||
|
||||
/**
|
||||
* 메인
|
||||
*
|
||||
* @param args 매개변수
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(BoardServiceApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
package org.egovframe.cloud.boardservice.api.board;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.egovframe.cloud.common.dto.RequestDto;
|
||||
import org.egovframe.cloud.boardservice.api.board.dto.BoardListResponseDto;
|
||||
import org.egovframe.cloud.boardservice.api.board.dto.BoardResponseDto;
|
||||
import org.egovframe.cloud.boardservice.api.board.dto.BoardSaveRequestDto;
|
||||
import org.egovframe.cloud.boardservice.api.board.dto.BoardUpdateRequestDto;
|
||||
import org.egovframe.cloud.boardservice.service.board.BoardService;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.web.PageableDefault;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.Valid;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.boardservice.api.board.BoardApiController
|
||||
* <p>
|
||||
* 게시판 Rest API 컨트롤러 클래스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/07/26
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/07/26 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
public class BoardApiController {
|
||||
|
||||
/**
|
||||
* 게시판 서비스
|
||||
*/
|
||||
private final BoardService boardService;
|
||||
|
||||
/**
|
||||
* 게시판 페이지 목록 조회
|
||||
*
|
||||
* @param requestDto 요청 DTO
|
||||
* @param pageable 페이지 정보
|
||||
* @return Page<BoardListResponseDto> 페이지 게시판 목록 응답 DTO
|
||||
*/
|
||||
@GetMapping("/api/v1/boards")
|
||||
public Page<BoardListResponseDto> findPage(RequestDto requestDto,
|
||||
@PageableDefault(sort = "board_no", direction = Sort.Direction.DESC) Pageable pageable) {
|
||||
return boardService.findPage(requestDto, pageable);
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시판 단건 조회
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @return BoardResponseDto 게시판 상세 응답 DTO
|
||||
*/
|
||||
@GetMapping("/api/v1/boards/{boardNo}")
|
||||
public BoardResponseDto findById(@PathVariable Integer boardNo) {
|
||||
return boardService.findById(boardNo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시판 등록
|
||||
*
|
||||
* @param requestDto 게시판 등록 요청 DTO
|
||||
* @return BoardResponseDto 게시판 상세 응답 DTO
|
||||
*/
|
||||
@PostMapping("/api/v1/boards")
|
||||
public BoardResponseDto save(@RequestBody @Valid BoardSaveRequestDto requestDto) {
|
||||
return boardService.save(requestDto);
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시판 수정
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param requestDto 게시판 수정 요청 DTO
|
||||
* @return BoardResponseDto 게시판 상세 응답 DTO
|
||||
*/
|
||||
@PutMapping("/api/v1/boards/{boardNo}")
|
||||
public BoardResponseDto update(@PathVariable Integer boardNo, @RequestBody @Valid BoardUpdateRequestDto requestDto) {
|
||||
return boardService.update(boardNo, requestDto);
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시판 삭제
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
*/
|
||||
@DeleteMapping("/api/v1/boards/{boardNo}")
|
||||
public void delete(@PathVariable Integer boardNo) {
|
||||
boardService.delete(boardNo);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package org.egovframe.cloud.boardservice.api.board.dto;
|
||||
|
||||
import com.querydsl.core.annotations.QueryProjection;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.boardservice.api.board.dto.BoardListResponseDto
|
||||
* <p>
|
||||
* 게시판 목록 응답 DTO 클래스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/07/26
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/07/26 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
public class BoardListResponseDto implements Serializable {
|
||||
|
||||
/**
|
||||
* SerialVersionUID
|
||||
*/
|
||||
private static final long serialVersionUID = 115181553377528728L;
|
||||
|
||||
/**
|
||||
* 게시판 번호
|
||||
*/
|
||||
private Integer boardNo;
|
||||
|
||||
/**
|
||||
* 게시판 명
|
||||
*/
|
||||
private String boardName;
|
||||
|
||||
/**
|
||||
* 스킨 유형 코드
|
||||
*/
|
||||
private String skinTypeCode;
|
||||
|
||||
/**
|
||||
* 스킨 유형 코드 명
|
||||
*/
|
||||
private String skinTypeCodeName;
|
||||
|
||||
/**
|
||||
* 생성 일시
|
||||
*/
|
||||
private LocalDateTime createdDate;
|
||||
|
||||
/**
|
||||
* 게시판 목록 응답 DTO 생성자
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param boardName 게시판 명
|
||||
* @param skinTypeCode 스킨 유형 코드
|
||||
*/
|
||||
@QueryProjection
|
||||
public BoardListResponseDto(Integer boardNo, String boardName, String skinTypeCode) {
|
||||
this.boardNo = boardNo;
|
||||
this.boardName = boardName;
|
||||
this.skinTypeCode = skinTypeCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시판 목록 응답 DTO 생성자
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param boardName 게시판 명
|
||||
* @param skinTypeCode 스킨 유형 코드
|
||||
* @param skinTypeCodeName 스킨 유형 코드 명
|
||||
* @param createdDate 생성 일시
|
||||
*/
|
||||
@QueryProjection
|
||||
public BoardListResponseDto(Integer boardNo, String boardName, String skinTypeCode, String skinTypeCodeName, LocalDateTime createdDate) {
|
||||
this.boardNo = boardNo;
|
||||
this.boardName = boardName;
|
||||
this.skinTypeCode = skinTypeCode;
|
||||
this.skinTypeCodeName = skinTypeCodeName;
|
||||
this.createdDate = createdDate;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
package org.egovframe.cloud.boardservice.api.board.dto;
|
||||
|
||||
import com.querydsl.core.annotations.QueryProjection;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.egovframe.cloud.boardservice.api.posts.dto.PostsSimpleResponseDto;
|
||||
import org.egovframe.cloud.boardservice.domain.board.Board;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.boardservice.api.board.dto.BoardResponseDto
|
||||
* <p>
|
||||
* 게시판 상세 응답 DTO 클래스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/07/26
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/07/26 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
public class BoardResponseDto implements Serializable {
|
||||
|
||||
/**
|
||||
* SerialVersionUID
|
||||
*/
|
||||
private static final long serialVersionUID = -7139346671431363426L;
|
||||
|
||||
/**
|
||||
* 게시판 번호
|
||||
*/
|
||||
private Integer boardNo;
|
||||
|
||||
/**
|
||||
* 게시판 제목
|
||||
*/
|
||||
private String boardName;
|
||||
|
||||
/**
|
||||
* 스킨 유형 코드
|
||||
*/
|
||||
private String skinTypeCode;
|
||||
|
||||
/**
|
||||
* 제목 표시 길이
|
||||
*/
|
||||
private Integer titleDisplayLength;
|
||||
|
||||
/**
|
||||
* 게시물 표시 수
|
||||
*/
|
||||
private Integer postDisplayCount;
|
||||
|
||||
/**
|
||||
* 페이지 표시 수
|
||||
*/
|
||||
private Integer pageDisplayCount;
|
||||
|
||||
/**
|
||||
* 표시 신규 수
|
||||
*/
|
||||
private Integer newDisplayDayCount;
|
||||
|
||||
/**
|
||||
* 에디터 사용 여부
|
||||
*/
|
||||
private Boolean editorUseAt;
|
||||
|
||||
/**
|
||||
* 사용자 작성 여부
|
||||
*/
|
||||
private Boolean userWriteAt;
|
||||
|
||||
/**
|
||||
* 댓글 사용 여부
|
||||
*/
|
||||
private Boolean commentUseAt;
|
||||
|
||||
/**
|
||||
* 업로드 사용 여부
|
||||
*/
|
||||
private Boolean uploadUseAt;
|
||||
|
||||
/**
|
||||
* 업로드 제한 수
|
||||
*/
|
||||
private Integer uploadLimitCount;
|
||||
|
||||
/**
|
||||
* 업로드 제한 크기
|
||||
*/
|
||||
private BigDecimal uploadLimitSize;
|
||||
|
||||
/**
|
||||
* 게시물 목록
|
||||
*/
|
||||
private List<PostsSimpleResponseDto> posts;
|
||||
|
||||
/**
|
||||
* 게시판 상세 응답 DTO 생성자
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param boardName 게시판 명
|
||||
* @param skinTypeCode 스킨 유형 코드
|
||||
* @param titleDisplayLength 제목 표시 길이
|
||||
* @param postDisplayCount 게시물 표시 수
|
||||
* @param pageDisplayCount 페이지 표시 수
|
||||
* @param newDisplayDayCount 신규 표시 일 수
|
||||
* @param editorUseAt 에디터 사용 여부
|
||||
* @param userWriteAt 사용자 작성 여부
|
||||
* @param commentUseAt 댓글 사용 여부
|
||||
* @param uploadUseAt 업로드 사용 여부
|
||||
* @param uploadLimitCount 업로드 제한 수
|
||||
* @param uploadLimitSize 업로드 제한 크기
|
||||
*/
|
||||
@QueryProjection
|
||||
public BoardResponseDto(Integer boardNo, String boardName, String skinTypeCode, Integer titleDisplayLength,
|
||||
Integer postDisplayCount, Integer pageDisplayCount, Integer newDisplayDayCount, Boolean editorUseAt,
|
||||
Boolean userWriteAt, Boolean commentUseAt, Boolean uploadUseAt, Integer uploadLimitCount,
|
||||
BigDecimal uploadLimitSize) {
|
||||
this.boardNo = boardNo;
|
||||
this.boardName = boardName;
|
||||
this.skinTypeCode = skinTypeCode;
|
||||
this.titleDisplayLength = titleDisplayLength;
|
||||
this.postDisplayCount = postDisplayCount;
|
||||
this.pageDisplayCount = pageDisplayCount;
|
||||
this.newDisplayDayCount = newDisplayDayCount;
|
||||
this.editorUseAt = editorUseAt;
|
||||
this.userWriteAt = userWriteAt;
|
||||
this.commentUseAt = commentUseAt;
|
||||
this.uploadUseAt = uploadUseAt;
|
||||
this.uploadLimitCount = uploadLimitCount;
|
||||
this.uploadLimitSize = uploadLimitSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시판 엔티티를 생성자로 주입 받아서 게시판 상세 응답 DTO 속성 값 세팅
|
||||
*
|
||||
* @param entity 게시판 엔티티
|
||||
*/
|
||||
public BoardResponseDto(Board entity) {
|
||||
this.boardNo = entity.getBoardNo();
|
||||
this.boardName = entity.getBoardName();
|
||||
this.skinTypeCode = entity.getSkinTypeCode();
|
||||
this.titleDisplayLength = entity.getTitleDisplayLength();
|
||||
this.postDisplayCount = entity.getPostDisplayCount();
|
||||
this.pageDisplayCount = entity.getPageDisplayCount();
|
||||
this.newDisplayDayCount = entity.getNewDisplayDayCount();
|
||||
this.editorUseAt = entity.getEditorUseAt();
|
||||
this.userWriteAt = entity.getUserWriteAt();
|
||||
this.commentUseAt = entity.getCommentUseAt();
|
||||
this.uploadUseAt = entity.getUploadUseAt();
|
||||
this.uploadLimitCount = entity.getUploadLimitCount();
|
||||
this.uploadLimitSize = entity.getUploadLimitSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시판 상세 응답 DTO 속성 값으로 게시판 엔티티 빌더를 사용하여 객체 생성
|
||||
*
|
||||
* @return Board 게시판 엔티티
|
||||
*/
|
||||
public Board toEntity() {
|
||||
return Board.builder()
|
||||
.boardNo(boardNo)
|
||||
.boardName(boardName)
|
||||
.skinTypeCode(skinTypeCode)
|
||||
.titleDisplayLength(titleDisplayLength)
|
||||
.postDisplayCount(postDisplayCount)
|
||||
.pageDisplayCount(pageDisplayCount)
|
||||
.newDisplayDayCount(newDisplayDayCount)
|
||||
.editorUseAt(editorUseAt)
|
||||
.userWriteAt(userWriteAt)
|
||||
.commentUseAt(commentUseAt)
|
||||
.uploadUseAt(uploadUseAt)
|
||||
.uploadLimitCount(uploadLimitCount)
|
||||
.uploadLimitSize(uploadLimitSize)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 최근 게시물 목록 세팅
|
||||
*
|
||||
* @param posts 게시물 목록
|
||||
*/
|
||||
public void setNewestPosts(List<PostsSimpleResponseDto> posts) {
|
||||
this.posts = posts;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
package org.egovframe.cloud.boardservice.api.board.dto;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.egovframe.cloud.boardservice.domain.board.Board;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.boardservice.api.board.dto.BoardSaveRequestDto
|
||||
* <p>
|
||||
* 게시판 등록 요청 DTO 클래스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/07/26
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/07/26 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
public class BoardSaveRequestDto {
|
||||
|
||||
/**
|
||||
* 게시판 제목
|
||||
*/
|
||||
@NotBlank(message = "{board.board_name} {err.required}")
|
||||
private String boardName;
|
||||
|
||||
/**
|
||||
* 스킨 유형 코드
|
||||
*/
|
||||
@NotBlank(message = "{board.skin_type_code} {err.required}")
|
||||
private String skinTypeCode;
|
||||
|
||||
/**
|
||||
* 제목 표시 길이
|
||||
*/
|
||||
@NotNull(message = "{board.title_display_length} {err.required}")
|
||||
private Integer titleDisplayLength;
|
||||
|
||||
/**
|
||||
* 게시물 표시 수
|
||||
*/
|
||||
@NotNull(message = "{board.post_display_count} {err.required}")
|
||||
private Integer postDisplayCount;
|
||||
|
||||
/**
|
||||
* 페이지 표시 수
|
||||
*/
|
||||
@NotNull(message = "{board.page_display_count} {err.required}")
|
||||
private Integer pageDisplayCount;
|
||||
|
||||
/**
|
||||
* 표시 신규 수
|
||||
*/
|
||||
@NotNull(message = "{board.new_display_day_count} {err.required}")
|
||||
private Integer newDisplayDayCount;
|
||||
|
||||
/**
|
||||
* 에디터 사용 여부
|
||||
*/
|
||||
@NotNull(message = "{board.editor_use_at} {err.required}")
|
||||
private Boolean editorUseAt;
|
||||
|
||||
/**
|
||||
* 사용자 작성 여부
|
||||
*/
|
||||
@NotNull(message = "{board.user_write_at} {err.required}")
|
||||
private Boolean userWriteAt;
|
||||
|
||||
/**
|
||||
* 댓글 사용 여부
|
||||
*/
|
||||
@NotNull(message = "{board.comment_use_at} {err.required}")
|
||||
private Boolean commentUseAt;
|
||||
|
||||
/**
|
||||
* 업로드 사용 여부
|
||||
*/
|
||||
@NotNull(message = "{board.upload_use_at} {err.required}")
|
||||
private Boolean uploadUseAt;
|
||||
|
||||
/**
|
||||
* 업로드 제한 수
|
||||
*/
|
||||
private Integer uploadLimitCount;
|
||||
|
||||
/**
|
||||
* 업로드 제한 크기
|
||||
*/
|
||||
private BigDecimal uploadLimitSize;
|
||||
|
||||
/**
|
||||
* 게시판 등록 요청 DTO 클래스 생성자
|
||||
* 빌더 패턴으로 객체 생성
|
||||
*
|
||||
* @param boardName 게시판 명
|
||||
* @param skinTypeCode 스킨 유형 코드
|
||||
* @param titleDisplayLength 제목 표시 길이
|
||||
* @param postDisplayCount 게시물 표시 수
|
||||
* @param pageDisplayCount 페이지 표시 수
|
||||
* @param newDisplayDayCount 신규 표시 일 수
|
||||
* @param editorUseAt 에디터 사용 여부
|
||||
* @param userWriteAt 사용자 작성 여부
|
||||
* @param commentUseAt 댓글 사용 여부
|
||||
* @param uploadUseAt 업로드 사용 여부
|
||||
* @param uploadLimitCount 업로드 제한 수
|
||||
* @param uploadLimitSize 업로드 제한 크기
|
||||
*/
|
||||
@Builder
|
||||
public BoardSaveRequestDto(String boardName, String skinTypeCode, Integer titleDisplayLength, Integer postDisplayCount,
|
||||
Integer pageDisplayCount, Integer newDisplayDayCount, Boolean editorUseAt, Boolean userWriteAt,
|
||||
Boolean commentUseAt, Boolean uploadUseAt, Integer uploadLimitCount, BigDecimal uploadLimitSize) {
|
||||
this.boardName = boardName;
|
||||
this.skinTypeCode = skinTypeCode;
|
||||
this.titleDisplayLength = titleDisplayLength;
|
||||
this.postDisplayCount = postDisplayCount;
|
||||
this.pageDisplayCount = pageDisplayCount;
|
||||
this.newDisplayDayCount = newDisplayDayCount;
|
||||
this.editorUseAt = editorUseAt;
|
||||
this.userWriteAt = userWriteAt;
|
||||
this.commentUseAt = commentUseAt;
|
||||
this.uploadUseAt = uploadUseAt;
|
||||
this.uploadLimitCount = uploadLimitCount;
|
||||
this.uploadLimitSize = uploadLimitSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시판 등록 요청 DTO 속성 값으로 게시판 엔티티 빌더를 사용하여 객체 생성
|
||||
*
|
||||
* @return Board 게시판 엔티티
|
||||
*/
|
||||
public Board toEntity() {
|
||||
return Board.builder()
|
||||
.boardName(boardName)
|
||||
.skinTypeCode(skinTypeCode)
|
||||
.titleDisplayLength(titleDisplayLength)
|
||||
.postDisplayCount(postDisplayCount)
|
||||
.pageDisplayCount(pageDisplayCount)
|
||||
.newDisplayDayCount(newDisplayDayCount)
|
||||
.editorUseAt(editorUseAt)
|
||||
.userWriteAt(userWriteAt)
|
||||
.commentUseAt(commentUseAt)
|
||||
.uploadUseAt(uploadUseAt)
|
||||
.uploadLimitCount(uploadLimitCount)
|
||||
.uploadLimitSize(uploadLimitSize)
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
package org.egovframe.cloud.boardservice.api.board.dto;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.egovframe.cloud.boardservice.domain.board.Board;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.boardservice.api.board.dto.BoardUpdateRequestDto
|
||||
* <p>
|
||||
* 게시판 수정 요청 DTO 클래스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/07/08
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/07/08 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
public class BoardUpdateRequestDto {
|
||||
|
||||
/**
|
||||
* 게시판 제목
|
||||
*/
|
||||
@NotBlank(message = "{board.board_name} {err.required}")
|
||||
private String boardName;
|
||||
|
||||
/**
|
||||
* 스킨 유형 코드
|
||||
*/
|
||||
@NotBlank(message = "{board.skin_type_code} {err.required}")
|
||||
private String skinTypeCode;
|
||||
|
||||
/**
|
||||
* 제목 표시 길이
|
||||
*/
|
||||
@NotNull(message = "{board.title_display_length} {err.required}")
|
||||
private Integer titleDisplayLength;
|
||||
|
||||
/**
|
||||
* 게시물 표시 수
|
||||
*/
|
||||
@NotNull(message = "{board.post_display_count} {err.required}")
|
||||
private Integer postDisplayCount;
|
||||
|
||||
/**
|
||||
* 페이지 표시 수
|
||||
*/
|
||||
@NotNull(message = "{board.page_display_count} {err.required}")
|
||||
private Integer pageDisplayCount;
|
||||
|
||||
/**
|
||||
* 표시 신규 수
|
||||
*/
|
||||
@NotNull(message = "{board.new_display_day_count} {err.required}")
|
||||
private Integer newDisplayDayCount;
|
||||
|
||||
/**
|
||||
* 에디터 사용 여부
|
||||
*/
|
||||
@NotNull(message = "{board.editor_use_at} {err.required}")
|
||||
private Boolean editorUseAt;
|
||||
|
||||
/**
|
||||
* 사용자 작성 여부
|
||||
*/
|
||||
@NotNull(message = "{board.user_write_at} {err.required}")
|
||||
private Boolean userWriteAt;
|
||||
|
||||
/**
|
||||
* 댓글 사용 여부
|
||||
*/
|
||||
@NotNull(message = "{board.comment_use_at} {err.required}")
|
||||
private Boolean commentUseAt;
|
||||
|
||||
/**
|
||||
* 업로드 사용 여부
|
||||
*/
|
||||
@NotNull(message = "{board.upload_use_at} {err.required}")
|
||||
private Boolean uploadUseAt;
|
||||
|
||||
/**
|
||||
* 업로드 제한 수
|
||||
*/
|
||||
private Integer uploadLimitCount;
|
||||
|
||||
/**
|
||||
* 업로드 제한 크기
|
||||
*/
|
||||
private BigDecimal uploadLimitSize;
|
||||
|
||||
/**
|
||||
* 게시판 등록 요청 DTO 클래스 생성자
|
||||
* 빌더 패턴으로 객체 생성
|
||||
*
|
||||
* @param boardName 게시판 명
|
||||
* @param skinTypeCode 스킨 유형 코드
|
||||
* @param titleDisplayLength 제목 표시 길이
|
||||
* @param postDisplayCount 게시물 표시 수
|
||||
* @param pageDisplayCount 페이지 표시 수
|
||||
* @param newDisplayDayCount 신규 표시 일 수
|
||||
* @param editorUseAt 에디터 사용 여부
|
||||
* @param userWriteAt 사용자 작성 여부
|
||||
* @param commentUseAt 댓글 사용 여부
|
||||
* @param uploadUseAt 업로드 사용 여부
|
||||
* @param uploadLimitCount 업로드 제한 수
|
||||
* @param uploadLimitSize 업로드 제한 크기
|
||||
*/
|
||||
@Builder
|
||||
public BoardUpdateRequestDto(String boardName, String skinTypeCode, Integer titleDisplayLength, Integer postDisplayCount,
|
||||
Integer pageDisplayCount, Integer newDisplayDayCount, Boolean editorUseAt, Boolean userWriteAt,
|
||||
Boolean commentUseAt, Boolean uploadUseAt, Integer uploadLimitCount, BigDecimal uploadLimitSize) {
|
||||
this.boardName = boardName;
|
||||
this.skinTypeCode = skinTypeCode;
|
||||
this.titleDisplayLength = titleDisplayLength;
|
||||
this.postDisplayCount = postDisplayCount;
|
||||
this.pageDisplayCount = pageDisplayCount;
|
||||
this.newDisplayDayCount = newDisplayDayCount;
|
||||
this.editorUseAt = editorUseAt;
|
||||
this.userWriteAt = userWriteAt;
|
||||
this.commentUseAt = commentUseAt;
|
||||
this.uploadUseAt = uploadUseAt;
|
||||
this.uploadLimitCount = uploadLimitCount;
|
||||
this.uploadLimitSize = uploadLimitSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시판 등록 요청 DTO 속성 값으로 게시판 엔티티 빌더를 사용하여 객체 생성
|
||||
*
|
||||
* @return Board 게시판 엔티티
|
||||
*/
|
||||
public Board toEntity() {
|
||||
return Board.builder()
|
||||
.boardName(boardName)
|
||||
.skinTypeCode(skinTypeCode)
|
||||
.titleDisplayLength(titleDisplayLength)
|
||||
.postDisplayCount(postDisplayCount)
|
||||
.pageDisplayCount(pageDisplayCount)
|
||||
.newDisplayDayCount(newDisplayDayCount)
|
||||
.editorUseAt(editorUseAt)
|
||||
.userWriteAt(userWriteAt)
|
||||
.commentUseAt(commentUseAt)
|
||||
.uploadUseAt(uploadUseAt)
|
||||
.uploadLimitCount(uploadLimitCount)
|
||||
.uploadLimitSize(uploadLimitSize)
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
package org.egovframe.cloud.boardservice.api.comment;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.egovframe.cloud.boardservice.api.comment.dto.CommentResponseDto;
|
||||
import org.egovframe.cloud.boardservice.api.comment.dto.CommentSaveRequestDto;
|
||||
import org.egovframe.cloud.boardservice.api.comment.dto.CommentUpdateRequestDto;
|
||||
import org.egovframe.cloud.boardservice.service.comment.CommentService;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.commentservice.api.comment.CommentApiController
|
||||
* <p>
|
||||
* 댓글 Rest API 컨트롤러 클래스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/08/04
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/08/04 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
public class CommentApiController {
|
||||
|
||||
/**
|
||||
* 댓글 서비스
|
||||
*/
|
||||
private final CommentService commentService;
|
||||
|
||||
/**
|
||||
* 게시글의 전체 댓글 목록 조회
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @return Map<String, Object> 페이지 댓글 목록 응답 DTO
|
||||
*/
|
||||
@GetMapping("/api/v1/comments/total/{boardNo}/{postsNo}")
|
||||
public Map<String, Object> findTotal(@PathVariable Integer boardNo, @PathVariable Integer postsNo) {
|
||||
return commentService.findAll(boardNo, postsNo, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시글의 전체 미삭제 댓글 목록 조회
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @return Map<String, Object> 페이지 댓글 목록 응답 DTO
|
||||
*/
|
||||
@GetMapping("/api/v1/comments/all/{boardNo}/{postsNo}")
|
||||
public Map<String, Object> findAll(@PathVariable Integer boardNo, @PathVariable Integer postsNo) {
|
||||
return commentService.findAll(boardNo, postsNo, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시글의 댓글 목록 조회
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @param pageable 페이지 정보
|
||||
* @return Map<String, Object> 페이지 댓글 목록 응답 DTO
|
||||
*/
|
||||
@GetMapping("/api/v1/comments/{boardNo}/{postsNo}")
|
||||
public Map<String, Object> findPage(@PathVariable Integer boardNo, @PathVariable Integer postsNo, Pageable pageable) {
|
||||
return commentService.findPage(boardNo, postsNo, null, pageable);
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시글의 미삭제 댓글 목록 조회
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @param pageable 페이지 정보
|
||||
* @return Map<String, Object> 페이지 댓글 목록 응답 DTO
|
||||
*/
|
||||
@GetMapping("/api/v1/comments/list/{boardNo}/{postsNo}")
|
||||
public Map<String, Object> findListPage(@PathVariable Integer boardNo, @PathVariable Integer postsNo, Pageable pageable) {
|
||||
return commentService.findPage(boardNo, postsNo, 0, pageable);
|
||||
}
|
||||
|
||||
/**
|
||||
* 댓글 등록
|
||||
*
|
||||
* @param requestDto 댓글 등록 요청 DTO
|
||||
*/
|
||||
@PostMapping("/api/v1/comments")
|
||||
public CommentResponseDto save(@RequestBody @Valid CommentSaveRequestDto requestDto) {
|
||||
return commentService.save(requestDto);
|
||||
}
|
||||
|
||||
/**
|
||||
* 댓글 수정(작성자 체크)
|
||||
*
|
||||
* @param requestDto 게시물 수정 요청 DTO
|
||||
* @return PostsResponseDto 게시물 상세 응답 DTO
|
||||
*/
|
||||
@PutMapping("/api/v1/comments/update")
|
||||
public CommentResponseDto updateByCreator(@RequestBody @Valid CommentUpdateRequestDto requestDto) {
|
||||
String userId = SecurityContextHolder.getContext().getAuthentication().getName();
|
||||
|
||||
return commentService.update(requestDto, userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 댓글 삭제(작성자 체크)
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @param commentNo 댓글 번호
|
||||
*/
|
||||
@DeleteMapping("/api/v1/comments/delete/{boardNo}/{postsNo}/{commentNo}")
|
||||
public void deleteByCreator(@PathVariable Integer boardNo, @PathVariable Integer postsNo, @PathVariable Integer commentNo) {
|
||||
String userId = SecurityContextHolder.getContext().getAuthentication().getName();
|
||||
|
||||
commentService.delete(boardNo, postsNo, commentNo, userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 댓글 수정
|
||||
*
|
||||
* @param requestDto 댓글 수정 요청 DTO
|
||||
*/
|
||||
@PutMapping("/api/v1/comments")
|
||||
public CommentResponseDto update(@RequestBody @Valid CommentUpdateRequestDto requestDto) {
|
||||
return commentService.update(requestDto);
|
||||
}
|
||||
|
||||
/**
|
||||
* 댓글 삭제
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @param commentNo 댓글 번호
|
||||
*/
|
||||
@DeleteMapping("/api/v1/comments/{boardNo}/{postsNo}/{commentNo}")
|
||||
public void delete(@PathVariable Integer boardNo, @PathVariable Integer postsNo, @PathVariable Integer commentNo) {
|
||||
commentService.delete(boardNo, postsNo, commentNo);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
package org.egovframe.cloud.boardservice.api.comment.dto;
|
||||
|
||||
import com.querydsl.core.annotations.QueryProjection;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.boardservice.api.comment.dto.CommentListResponseDto
|
||||
* <p>
|
||||
* 댓글 목록 응답 DTO 클래스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/08/04
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/08/04 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
public class CommentListResponseDto implements Serializable {
|
||||
|
||||
/**
|
||||
* SerialVersionUID
|
||||
*/
|
||||
private static final long serialVersionUID = -8163130888886378482L;
|
||||
|
||||
/**
|
||||
* 게시판 번호
|
||||
*/
|
||||
private Integer boardNo;
|
||||
|
||||
/**
|
||||
* 게시물 번호
|
||||
*/
|
||||
private Integer postsNo;
|
||||
|
||||
/**
|
||||
* 댓글 번호
|
||||
*/
|
||||
private Integer commentNo;
|
||||
|
||||
/**
|
||||
* 댓글 내용
|
||||
*/
|
||||
private String commentContent;
|
||||
|
||||
/**
|
||||
* 그룹 번호
|
||||
*/
|
||||
private Integer groupNo;
|
||||
|
||||
/**
|
||||
* 부모 댓글 번호
|
||||
*/
|
||||
private Integer parentCommentNo;
|
||||
|
||||
/**
|
||||
* 깊이 순서
|
||||
*/
|
||||
private Integer depthSeq;
|
||||
|
||||
/**
|
||||
* 정렬 순서
|
||||
*/
|
||||
private Integer sortSeq;
|
||||
|
||||
/**
|
||||
* 삭제 여부
|
||||
*/
|
||||
private Integer deleteAt;
|
||||
|
||||
/**
|
||||
* 생성자 id
|
||||
*/
|
||||
private String createdBy;
|
||||
|
||||
/**
|
||||
* 생성자 명
|
||||
*/
|
||||
private String createdName;
|
||||
|
||||
/**
|
||||
* 생성 일시
|
||||
*/
|
||||
private LocalDateTime createdDate;
|
||||
|
||||
/**
|
||||
* 댓글 목록 응답 DTO 생성자
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @param commentNo 댓글 번호
|
||||
* @param commentContent 댓글 내용
|
||||
* @param parentCommentNo 부모 댓글 번호
|
||||
* @param depthSeq 깊이 순서
|
||||
* @param sortSeq 정렬 순서
|
||||
* @param deleteAt 삭제 여부
|
||||
* @param createdBy 생성자 id
|
||||
* @param createdName 생성자 명
|
||||
* @param createdDate 생성 일시
|
||||
*/
|
||||
@QueryProjection
|
||||
public CommentListResponseDto(Integer boardNo, Integer postsNo, Integer commentNo,
|
||||
String commentContent, Integer groupNo, Integer parentCommentNo,
|
||||
Integer depthSeq, Integer sortSeq, Integer deleteAt,
|
||||
String createdBy, String createdName, LocalDateTime createdDate) {
|
||||
this.boardNo = boardNo;
|
||||
this.postsNo = postsNo;
|
||||
this.commentNo = commentNo;
|
||||
this.commentContent = commentContent;
|
||||
this.groupNo = groupNo;
|
||||
this.parentCommentNo = parentCommentNo;
|
||||
this.depthSeq = depthSeq;
|
||||
this.sortSeq = sortSeq;
|
||||
this.deleteAt = deleteAt;
|
||||
this.createdBy = createdBy;
|
||||
this.createdName = createdName;
|
||||
this.createdDate = createdDate;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
package org.egovframe.cloud.boardservice.api.comment.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.egovframe.cloud.boardservice.domain.comment.Comment;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.boardservice.api.comment.dto.CommentResponseDto
|
||||
*
|
||||
* 댓글 상세 응답 DTO 클래스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/08/11
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/08/11 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
public class CommentResponseDto implements Serializable {
|
||||
|
||||
/**
|
||||
* SerialVersionUID
|
||||
*/
|
||||
private static final long serialVersionUID = -3087424580328463654L;
|
||||
|
||||
/**
|
||||
* 게시판 번호
|
||||
*/
|
||||
private Integer boardNo;
|
||||
|
||||
/**
|
||||
* 게시물 번호
|
||||
*/
|
||||
private Integer postsNo;
|
||||
|
||||
/**
|
||||
* 댓글 번호
|
||||
*/
|
||||
private Integer commentNo;
|
||||
|
||||
/**
|
||||
* 댓글 내용
|
||||
*/
|
||||
private String commentContent;
|
||||
|
||||
/**
|
||||
* 그룹 번호
|
||||
*/
|
||||
private Integer groupNo;
|
||||
|
||||
/**
|
||||
* 부모 댓글 번호
|
||||
*/
|
||||
private Integer parentCommentNo;
|
||||
|
||||
/**
|
||||
* 깊이 순서
|
||||
*/
|
||||
private Integer depthSeq;
|
||||
|
||||
/**
|
||||
* 정렬 순서
|
||||
*/
|
||||
private Integer sortSeq;
|
||||
|
||||
/**
|
||||
* 삭제 여부
|
||||
*/
|
||||
private Integer deleteAt;
|
||||
|
||||
/**
|
||||
* 생성자 id
|
||||
*/
|
||||
private String createdBy;
|
||||
|
||||
/**
|
||||
* 생성자 명
|
||||
*/
|
||||
private String createdName;
|
||||
|
||||
/**
|
||||
* 생성 일시
|
||||
*/
|
||||
private LocalDateTime createdDate;
|
||||
|
||||
/**
|
||||
* 댓글 엔티티를 생성자로 주입 받아서 댓글 상세 응답 DTO 속성 값 세팅
|
||||
*
|
||||
* @param entity 댓글 엔티티
|
||||
*/
|
||||
public CommentResponseDto(Comment entity) {
|
||||
this.postsNo = entity.getCommentId().getPostsId().getPostsNo();
|
||||
this.boardNo = entity.getCommentId().getPostsId().getBoardNo();
|
||||
this.commentNo = entity.getCommentId().getCommentNo();
|
||||
this.commentContent = entity.getCommentContent();
|
||||
this.groupNo = entity.getGroupNo();
|
||||
this.parentCommentNo = entity.getParentCommentNo();
|
||||
this.depthSeq = entity.getDepthSeq();
|
||||
this.sortSeq = entity.getSortSeq();
|
||||
this.deleteAt = entity.getDeleteAt();
|
||||
this.createdBy = entity.getCreatedBy();
|
||||
this.createdName = entity.getCreator() != null ? entity.getCreator().getUserName() : null;
|
||||
this.createdDate = entity.getCreatedDate();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
package org.egovframe.cloud.boardservice.api.comment.dto;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.egovframe.cloud.boardservice.domain.comment.Comment;
|
||||
import org.egovframe.cloud.boardservice.domain.comment.CommentId;
|
||||
import org.egovframe.cloud.boardservice.domain.posts.Posts;
|
||||
import org.egovframe.cloud.boardservice.domain.posts.PostsId;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.boardservice.api.comment.dto.CommentSaveRequestDto
|
||||
* <p>
|
||||
* 댓글 등록 요청 DTO 클래스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/08/04
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/08/04 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
public class CommentSaveRequestDto {
|
||||
|
||||
/**
|
||||
* 게시판 번호
|
||||
*/
|
||||
@NotNull(message = "{board.board_no} {err.required}")
|
||||
private Integer boardNo;
|
||||
|
||||
/**
|
||||
* 게시물 번호
|
||||
*/
|
||||
@NotNull(message = "{posts.posts_no} {err.required}")
|
||||
private Integer postsNo;
|
||||
|
||||
/**
|
||||
* 댓글 내용
|
||||
*/
|
||||
@NotBlank(message = "{comment.comment_content} {err.required}")
|
||||
private String commentContent;
|
||||
|
||||
/**
|
||||
* 그룹 번호
|
||||
*/
|
||||
private Integer groupNo;
|
||||
|
||||
/**
|
||||
* 부모 댓글 번호
|
||||
*/
|
||||
private Integer parentCommentNo;
|
||||
|
||||
/**
|
||||
* 깊이 순서
|
||||
*/
|
||||
private Integer depthSeq;
|
||||
|
||||
/**
|
||||
* 댓글 등록 요청 DTO 클래스 생성자
|
||||
* 빌더 패턴으로 객체 생성
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @param commentContent 댓글 내용
|
||||
* @param groupNo 그룹 번호
|
||||
* @param parentCommentNo 부모 댓글 번호
|
||||
* @param depthSeq 깊이 순서
|
||||
*/
|
||||
@Builder
|
||||
public CommentSaveRequestDto(Integer boardNo, Integer postsNo, String commentContent, Integer groupNo, Integer parentCommentNo, Integer depthSeq) {
|
||||
this.boardNo = boardNo;
|
||||
this.postsNo = postsNo;
|
||||
this.commentContent = commentContent;
|
||||
this.groupNo = groupNo;
|
||||
this.parentCommentNo = parentCommentNo;
|
||||
this.depthSeq = depthSeq;
|
||||
}
|
||||
|
||||
/**
|
||||
* 댓글 등록 요청 DTO 속성 값으로 댓글 엔티티 빌더를 사용하여 객체 생성
|
||||
*
|
||||
* @param commentNo 댓글 번호
|
||||
* @param sortSeq 정렬 순서
|
||||
* @return Comment 댓글 엔티티
|
||||
*/
|
||||
public Comment toEntity(Integer commentNo, Integer sortSeq) {
|
||||
return Comment.builder()
|
||||
.commentId(CommentId.builder()
|
||||
.postsId(PostsId.builder()
|
||||
.boardNo(boardNo)
|
||||
.postsNo(postsNo)
|
||||
.build())
|
||||
.commentNo(commentNo)
|
||||
.build())
|
||||
.commentContent(commentContent)
|
||||
.groupNo(groupNo)
|
||||
.parentCommentNo(parentCommentNo)
|
||||
.depthSeq(depthSeq)
|
||||
.sortSeq(sortSeq)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 댓글 등록 요청 DTO 속성 값으로 댓글 엔티티 빌더를 사용하여 객체 생성
|
||||
*
|
||||
* @param posts 게시물 엔티티
|
||||
* @param commentNo 댓글 번호
|
||||
* @param groupNo 그룹 번호
|
||||
* @param sortSeq 정렬 순서
|
||||
* @return Comment 댓글 엔티티
|
||||
*/
|
||||
public Comment toEntity(Posts posts, Integer commentNo, Integer groupNo, Integer sortSeq) {
|
||||
return Comment.builder()
|
||||
.posts(posts)
|
||||
.commentId(CommentId.builder()
|
||||
.postsId(posts.getPostsId())
|
||||
.commentNo(commentNo)
|
||||
.build())
|
||||
.commentContent(commentContent)
|
||||
.groupNo(groupNo)
|
||||
.parentCommentNo(parentCommentNo)
|
||||
.depthSeq(depthSeq)
|
||||
.sortSeq(sortSeq)
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package org.egovframe.cloud.boardservice.api.comment.dto;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.egovframe.cloud.boardservice.domain.comment.Comment;
|
||||
import org.egovframe.cloud.boardservice.domain.comment.CommentId;
|
||||
import org.egovframe.cloud.boardservice.domain.posts.PostsId;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.boardservice.api.comment.dto.CommentSaveRequestDto
|
||||
*
|
||||
* 댓글 수정 요청 DTO 클래스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/08/04
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/08/04 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
public class CommentUpdateRequestDto {
|
||||
|
||||
/**
|
||||
* 게시판 번호
|
||||
*/
|
||||
@NotNull(message = "{board.board_no} {err.required}")
|
||||
private Integer boardNo;
|
||||
|
||||
/**
|
||||
* 게시물 번호
|
||||
*/
|
||||
@NotNull(message = "{posts.posts_no} {err.required}")
|
||||
private Integer postsNo;
|
||||
|
||||
/**
|
||||
* 댓글 번호
|
||||
*/
|
||||
@NotNull(message = "{comment.comment_no} {err.required}")
|
||||
private Integer commentNo;
|
||||
|
||||
/**
|
||||
* 댓글 내용
|
||||
*/
|
||||
@NotBlank(message = "{comment.comment_content} {err.required}")
|
||||
private String commentContent;
|
||||
|
||||
/**
|
||||
* 댓글 수정 요청 DTO 클래스 생성자
|
||||
* 빌더 패턴으로 객체 생성
|
||||
*
|
||||
* @param commentContent 댓글 내용
|
||||
*/
|
||||
@Builder
|
||||
public CommentUpdateRequestDto(Integer boardNo, Integer postsNo, Integer commentNo, String commentContent) {
|
||||
this.boardNo = boardNo;
|
||||
this.postsNo = postsNo;
|
||||
this.commentNo = commentNo;
|
||||
this.commentContent = commentContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* 댓글 수정 요청 DTO 속성 값으로 댓글 엔티티 빌더를 사용하여 객체 생성
|
||||
*
|
||||
* @return Comment 댓글 엔티티
|
||||
*/
|
||||
public Comment toEntity() {
|
||||
return Comment.builder()
|
||||
.commentId(CommentId.builder()
|
||||
.postsId(PostsId.builder()
|
||||
.boardNo(boardNo)
|
||||
.postsNo(postsNo)
|
||||
.build())
|
||||
.commentNo(commentNo)
|
||||
.build())
|
||||
.commentContent(commentContent)
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,229 @@
|
||||
package org.egovframe.cloud.boardservice.api.posts;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.egovframe.cloud.boardservice.api.board.dto.BoardResponseDto;
|
||||
import org.egovframe.cloud.boardservice.api.posts.dto.*;
|
||||
import org.egovframe.cloud.boardservice.service.posts.PostsService;
|
||||
import org.egovframe.cloud.common.dto.RequestDto;
|
||||
import org.egovframe.cloud.common.util.LogUtil;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.web.SortDefault;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.postservice.api.posts.PostsApiController
|
||||
* <p>
|
||||
* 게시물 Rest API 컨트롤러 클래스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/07/28
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/07/28 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
public class PostsApiController {
|
||||
|
||||
/**
|
||||
* 게시물 서비스
|
||||
*/
|
||||
private final PostsService postsService;
|
||||
|
||||
/**
|
||||
* 게시물(삭제 포함) 페이지 목록 조회
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param requestDto 요청 DTO
|
||||
* @param pageable 페이지 정보
|
||||
* @return Page<PostsListResponseDto> 페이지 게시물 목록 응답 DTO
|
||||
*/
|
||||
@GetMapping("/api/v1/posts/{boardNo}")
|
||||
public Page<PostsListResponseDto> findPage(@PathVariable Integer boardNo,
|
||||
RequestDto requestDto,
|
||||
@SortDefault.SortDefaults({
|
||||
@SortDefault(sort = "notice_at", direction = Sort.Direction.DESC),
|
||||
@SortDefault(sort = "board_no", direction = Sort.Direction.ASC),
|
||||
@SortDefault(sort = "posts_no", direction = Sort.Direction.DESC)
|
||||
}) Pageable pageable) {
|
||||
return postsService.findPage(boardNo, null, requestDto, pageable);
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물(삭제 제외) 페이지 목록 조회
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param requestDto 요청 DTO
|
||||
* @param pageable 페이지 정보
|
||||
* @return Page<PostsListResponseDto> 페이지 게시물 목록 응답 DTO
|
||||
*/
|
||||
@GetMapping("/api/v1/posts/list/{boardNo}")
|
||||
public Page<PostsListResponseDto> findListPage(@PathVariable Integer boardNo,
|
||||
RequestDto requestDto,
|
||||
@SortDefault.SortDefaults({
|
||||
@SortDefault(sort = "notice_at", direction = Sort.Direction.DESC),
|
||||
@SortDefault(sort = "board_no", direction = Sort.Direction.ASC),
|
||||
@SortDefault(sort = "posts_no", direction = Sort.Direction.DESC)
|
||||
}) Pageable pageable) {
|
||||
return postsService.findPage(boardNo, 0, requestDto, pageable);
|
||||
}
|
||||
|
||||
/**
|
||||
* 최근 게시물이 포함된 게시판 목록 조회
|
||||
*
|
||||
* @param boardNos 게시판 번호 목록
|
||||
* @param postsCount 게시물 수
|
||||
* @return Map<Integer, BoardResponseDto> 최근 게시물이 포함된 게시판 상세 응답 DTO Map
|
||||
*/
|
||||
@GetMapping("/api/v1/posts/newest/{boardNos}/{postsCount}")
|
||||
public Map<Integer, BoardResponseDto> findNewest(@PathVariable List<Integer> boardNos, @PathVariable Integer postsCount) {
|
||||
return postsService.findNewest(boardNos, postsCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물(삭제 포함) 단건 조회
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @return PostsResponseDto 게시물 상세 응답 DTO
|
||||
*/
|
||||
@GetMapping("/api/v1/posts/{boardNo}/{postsNo}")
|
||||
public PostsResponseDto findById(@PathVariable Integer boardNo, @PathVariable Integer postsNo) {
|
||||
String userId = SecurityContextHolder.getContext().getAuthentication().getName();
|
||||
userId = "anonymousUser".equals(userId) ? null : userId;
|
||||
|
||||
return postsService.findById(boardNo, postsNo, null, userId, LogUtil.getUserIp());
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물(삭제 제외) 단건 조회
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @return PostsResponseDto 게시물 상세 응답 DTO
|
||||
*/
|
||||
@GetMapping("/api/v1/posts/view/{boardNo}/{postsNo}")
|
||||
public PostsResponseDto findViewById(@PathVariable Integer boardNo, @PathVariable Integer postsNo, RequestDto requestDto) {
|
||||
String userId = SecurityContextHolder.getContext().getAuthentication().getName();
|
||||
userId = "anonymousUser".equals(userId) ? null : userId;
|
||||
final Integer deleteAt = 0; // 미삭제 게시물만 조회
|
||||
|
||||
return postsService.findById(boardNo, postsNo, deleteAt, userId, LogUtil.getUserIp(), requestDto);
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물 등록(작성자 체크)
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param requestDto 게시물 등록 요청 DTO
|
||||
* @return PostsResponseDto 게시물 상세 응답 DTO
|
||||
*/
|
||||
@PostMapping("/api/v1/posts/save/{boardNo}")
|
||||
public PostsResponseDto saveByCreator(@PathVariable Integer boardNo, @RequestBody @Valid PostsSimpleSaveRequestDto requestDto) {
|
||||
String userId = SecurityContextHolder.getContext().getAuthentication().getName();
|
||||
return postsService.save(boardNo, requestDto, userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물 수정(작성자 체크)
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @param requestDto 게시물 수정 요청 DTO
|
||||
* @return PostsResponseDto 게시물 상세 응답 DTO
|
||||
*/
|
||||
@PutMapping("/api/v1/posts/update/{boardNo}/{postsNo}")
|
||||
public PostsResponseDto updateByCreator(@PathVariable Integer boardNo, @PathVariable Integer postsNo, @RequestBody @Valid PostsSimpleSaveRequestDto requestDto) {
|
||||
String userId = SecurityContextHolder.getContext().getAuthentication().getName();
|
||||
|
||||
return postsService.update(boardNo, postsNo, requestDto, userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물 삭제(작성자 체크)
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
*/
|
||||
@DeleteMapping("/api/v1/posts/remove/{boardNo}/{postsNo}")
|
||||
public void deleteByCreator(@PathVariable Integer boardNo, @PathVariable Integer postsNo) {
|
||||
String userId = SecurityContextHolder.getContext().getAuthentication().getName();
|
||||
|
||||
postsService.remove(boardNo, postsNo, userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물 등록
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param requestDto 게시물 등록 요청 DTO
|
||||
* @return PostsResponseDto 게시물 상세 응답 DTO
|
||||
*/
|
||||
@PostMapping("/api/v1/posts/{boardNo}")
|
||||
public PostsResponseDto save(@PathVariable Integer boardNo, @RequestBody @Valid PostsSaveRequestDto requestDto) {
|
||||
return postsService.save(boardNo, requestDto);
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물 수정
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @param requestDto 게시물 수정 요청 DTO
|
||||
* @return PostsResponseDto 게시물 상세 응답 DTO
|
||||
*/
|
||||
@PutMapping("/api/v1/posts/{boardNo}/{postsNo}")
|
||||
public PostsResponseDto update(@PathVariable Integer boardNo, @PathVariable Integer postsNo, @RequestBody @Valid PostsUpdateRequestDto requestDto) {
|
||||
return postsService.update(boardNo, postsNo, requestDto);
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물 다건 삭제
|
||||
*
|
||||
* @param requestDtoList 게시물 삭제 요청 DTO List
|
||||
* @return Long 삭제 건수
|
||||
*/
|
||||
@PutMapping("/api/v1/posts/remove")
|
||||
public Long remove(@RequestBody @Valid List<PostsDeleteRequestDto> requestDtoList) {
|
||||
String userId = SecurityContextHolder.getContext().getAuthentication().getName();
|
||||
|
||||
return postsService.remove(requestDtoList, userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물 다건 복원
|
||||
*
|
||||
* @param requestDtoList 게시물 삭제 요청 DTO List
|
||||
* @return Long 복원 건수
|
||||
*/
|
||||
@PutMapping("/api/v1/posts/restore")
|
||||
public Long restore(@RequestBody @Valid List<PostsDeleteRequestDto> requestDtoList) {
|
||||
String userId = SecurityContextHolder.getContext().getAuthentication().getName();
|
||||
|
||||
return postsService.restore(requestDtoList, userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물 다건 완전 삭제
|
||||
*
|
||||
* @param requestDtoList 게시물 삭제 요청 DTO List
|
||||
*/
|
||||
@PutMapping("/api/v1/posts/delete")
|
||||
public void delete(@RequestBody @Valid List<PostsDeleteRequestDto> requestDtoList) {
|
||||
postsService.delete(requestDtoList);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package org.egovframe.cloud.boardservice.api.posts.dto;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.egovframe.cloud.boardservice.domain.posts.Posts;
|
||||
import org.egovframe.cloud.boardservice.domain.posts.PostsId;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.boardservice.api.posts.dto.PostsDeleteRequestDto
|
||||
* <p>
|
||||
* 게시물 삭제 요청 DTO 클래스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/07/29
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/07/29 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@Getter
|
||||
public class PostsDeleteRequestDto {
|
||||
|
||||
/**
|
||||
* 게시판 번호
|
||||
*/
|
||||
@NotBlank(message = "{board.board_no} {err.required}")
|
||||
private Integer boardNo;
|
||||
|
||||
/**
|
||||
* 게시물 번호
|
||||
*/
|
||||
@NotBlank(message = "{posts.posts_no} {err.required}")
|
||||
private Integer postsNo;
|
||||
|
||||
/**
|
||||
* 게시물 삭제 요청 DTO 속성 값으로 게시물 엔티티 빌더를 사용하여 객체 생성
|
||||
*
|
||||
* @return Posts 게시물 엔티티
|
||||
*/
|
||||
public Posts toEntity() {
|
||||
return Posts.builder()
|
||||
.postsId(PostsId.builder()
|
||||
.boardNo(boardNo)
|
||||
.postsNo(postsNo)
|
||||
.build())
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
package org.egovframe.cloud.boardservice.api.posts.dto;
|
||||
|
||||
import com.querydsl.core.annotations.QueryProjection;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.boardservice.api.board.dto.PostsListResponseDto
|
||||
* <p>
|
||||
* 게시물 목록 응답 DTO 클래스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/07/28
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/07/28 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
public class PostsListResponseDto implements Serializable {
|
||||
|
||||
/**
|
||||
* SerialVersionUID
|
||||
*/
|
||||
private static final long serialVersionUID = 3316086575500238046L;
|
||||
|
||||
/**
|
||||
* 게시판 번호
|
||||
*/
|
||||
private Integer boardNo;
|
||||
|
||||
/**
|
||||
* 게시물 번호
|
||||
*/
|
||||
private Integer postsNo;
|
||||
|
||||
/**
|
||||
* 게시물 제목
|
||||
*/
|
||||
private String postsTitle;
|
||||
|
||||
/**
|
||||
* 게시물 내용
|
||||
*/
|
||||
private String postsContent;
|
||||
|
||||
/**
|
||||
* 게시물 답변 내용
|
||||
*/
|
||||
private String postsAnswerContent;
|
||||
|
||||
/**
|
||||
* 조회 수
|
||||
*/
|
||||
private Integer readCount;
|
||||
|
||||
/**
|
||||
* 공지 여부
|
||||
*/
|
||||
private Boolean noticeAt;
|
||||
|
||||
/**
|
||||
* 삭제 여부
|
||||
*/
|
||||
private Integer deleteAt;
|
||||
|
||||
/**
|
||||
* 생성자 id
|
||||
*/
|
||||
private String createdBy;
|
||||
|
||||
/**
|
||||
* 생성자 명
|
||||
*/
|
||||
private String createdName;
|
||||
|
||||
/**
|
||||
* 생성 일시
|
||||
*/
|
||||
private LocalDateTime createdDate;
|
||||
|
||||
/**
|
||||
* 신규 여부
|
||||
*/
|
||||
private Boolean isNew;
|
||||
|
||||
/**
|
||||
* 댓글 수
|
||||
*/
|
||||
private Long commentCount;
|
||||
|
||||
/**
|
||||
* 게시물 목록 응답 DTO 생성자
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @param postsTitle 게시물 제목
|
||||
* @param postsContent 게시물 내용
|
||||
* @param postsAnswerContent 게시물 답변 내용
|
||||
* @param readCount 조회 수
|
||||
* @param noticeAt 공지 여부
|
||||
* @param deleteAt 삭제 여부
|
||||
* @param createdBy 생성자 id
|
||||
* @param createdName 생성자 명
|
||||
* @param createdDate 생성 일시
|
||||
* @param commentCount 댓글 수
|
||||
*/
|
||||
@QueryProjection
|
||||
public PostsListResponseDto(Integer boardNo, Integer postsNo, String postsTitle, String postsContent,
|
||||
String postsAnswerContent, Integer readCount, Boolean noticeAt, Integer deleteAt,
|
||||
String createdBy, String createdName, LocalDateTime createdDate, Integer newDisplayDayCount,
|
||||
Long commentCount) {
|
||||
this.boardNo = boardNo;
|
||||
this.postsNo = postsNo;
|
||||
this.postsTitle = postsTitle;
|
||||
this.postsContent = postsContent;
|
||||
this.postsAnswerContent = postsAnswerContent;
|
||||
this.readCount = readCount;
|
||||
this.noticeAt = noticeAt;
|
||||
this.deleteAt = deleteAt;
|
||||
this.createdBy = createdBy;
|
||||
this.createdName = createdName;
|
||||
this.createdDate = createdDate;
|
||||
this.isNew = createdDate.plusDays(newDisplayDayCount).compareTo(LocalDateTime.now()) >= 0;
|
||||
this.commentCount = commentCount;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,215 @@
|
||||
package org.egovframe.cloud.boardservice.api.posts.dto;
|
||||
|
||||
import com.querydsl.core.annotations.QueryProjection;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.egovframe.cloud.boardservice.api.board.dto.BoardResponseDto;
|
||||
import org.egovframe.cloud.boardservice.domain.posts.Posts;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.boardservice.api.board.dto.PostsResponseDto
|
||||
* <p>
|
||||
* 게시물 상세 응답 DTO 클래스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/07/28
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/07/28 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
public class PostsResponseDto implements Serializable {
|
||||
|
||||
/**
|
||||
* SerialVersionUID
|
||||
*/
|
||||
private static final long serialVersionUID = 8644170429040511387L;
|
||||
|
||||
/**
|
||||
* 게시판 번호
|
||||
*/
|
||||
private Integer boardNo;
|
||||
|
||||
/**
|
||||
* 게시물 번호
|
||||
*/
|
||||
private Integer postsNo;
|
||||
|
||||
/**
|
||||
* 게시물 제목
|
||||
*/
|
||||
private String postsTitle;
|
||||
|
||||
/**
|
||||
* 게시물 내용
|
||||
*/
|
||||
private String postsContent;
|
||||
|
||||
/**
|
||||
* 게시물 답변 내용
|
||||
*/
|
||||
private String postsAnswerContent;
|
||||
|
||||
/**
|
||||
* 첨부파일 코드
|
||||
*/
|
||||
private String attachmentCode;
|
||||
|
||||
/**
|
||||
* 조회 수
|
||||
*/
|
||||
private Integer readCount;
|
||||
|
||||
/**
|
||||
* 공지 여부
|
||||
*/
|
||||
private Boolean noticeAt;
|
||||
|
||||
/**
|
||||
* 삭제 여부
|
||||
*/
|
||||
private Integer deleteAt;
|
||||
|
||||
/**
|
||||
* 생성자
|
||||
*/
|
||||
private String createdBy;
|
||||
|
||||
/**
|
||||
* 생성자 명
|
||||
*/
|
||||
private String createdName;
|
||||
|
||||
/**
|
||||
* 생성 일시
|
||||
*/
|
||||
private LocalDateTime createdDate;
|
||||
|
||||
/**
|
||||
* 게시판 응답 DTO
|
||||
*/
|
||||
private BoardResponseDto board;
|
||||
|
||||
/**
|
||||
* 신규 여부
|
||||
*/
|
||||
private Boolean isNew;
|
||||
|
||||
/**
|
||||
* 유저 게시물 조회 수
|
||||
*/
|
||||
private Long userPostsReadCount;
|
||||
|
||||
/**
|
||||
* 이전 게시물 응답 DTO List
|
||||
*/
|
||||
private List<PostsSimpleResponseDto> prevPosts;
|
||||
|
||||
/**
|
||||
* 다음 게시물 응답 DTO List
|
||||
*/
|
||||
private List<PostsSimpleResponseDto> nextPosts;
|
||||
|
||||
/**
|
||||
* 게시물 상세 응답 DTO 생성자
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @param postsTitle 게시물 제목
|
||||
* @param postsContent 게시물 내용
|
||||
* @param postsAnswerContent 게시물 답변 내용
|
||||
* @param attachmentCode 첨부파일 코드
|
||||
* @param readCount 조회 수
|
||||
* @param noticeAt 공지 여부
|
||||
* @param deleteAt 삭제 여부
|
||||
* @param createdBy 생성자 id
|
||||
* @param createdName 생성자 명
|
||||
* @param createdDate 생성 일시
|
||||
* @param board 게시판
|
||||
* @param userPostsReadCount 유저 게시물 조회 수
|
||||
*/
|
||||
@QueryProjection
|
||||
public PostsResponseDto(Integer boardNo, Integer postsNo, String postsTitle, String postsContent,
|
||||
String postsAnswerContent, String attachmentCode, Integer readCount, Boolean noticeAt,
|
||||
Integer deleteAt, String createdBy, String createdName, LocalDateTime createdDate,
|
||||
BoardResponseDto board, Long userPostsReadCount) {
|
||||
this.boardNo = boardNo;
|
||||
this.postsNo = postsNo;
|
||||
this.postsTitle = postsTitle;
|
||||
this.postsContent = postsContent;
|
||||
this.postsAnswerContent = postsAnswerContent;
|
||||
this.attachmentCode = attachmentCode;
|
||||
this.readCount = readCount;
|
||||
this.noticeAt = noticeAt;
|
||||
this.deleteAt = deleteAt;
|
||||
this.createdBy = createdBy;
|
||||
this.createdName = createdName;
|
||||
this.createdDate = createdDate;
|
||||
this.board = board;
|
||||
if (this.board.getNewDisplayDayCount() != null && this.board.getNewDisplayDayCount() > 0) {
|
||||
this.isNew = createdDate.plusDays(this.board.getNewDisplayDayCount()).compareTo(LocalDateTime.now()) <= 0;
|
||||
} else {
|
||||
this.isNew = false;
|
||||
}
|
||||
this.userPostsReadCount = userPostsReadCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물 엔티티를 생성자로 주입 받아서 게시물 상세 응답 DTO 속성 값 세팅
|
||||
*
|
||||
* @param entity 게시물 엔티티
|
||||
*/
|
||||
public PostsResponseDto(Posts entity) {
|
||||
this.postsNo = entity.getPostsId().getPostsNo();
|
||||
this.boardNo = entity.getPostsId().getBoardNo();
|
||||
this.postsTitle = entity.getPostsTitle();
|
||||
this.postsContent = entity.getPostsContent();
|
||||
this.postsAnswerContent = entity.getPostsAnswerContent();
|
||||
this.attachmentCode = entity.getAttachmentCode();
|
||||
this.readCount = entity.getReadCount();
|
||||
this.noticeAt = entity.getNoticeAt();
|
||||
this.deleteAt = entity.getDeleteAt();
|
||||
this.createdBy = entity.getCreatedBy();
|
||||
this.createdName = entity.getCreator() != null ? entity.getCreator().getUserName() : null;
|
||||
this.createdDate = entity.getCreatedDate();
|
||||
this.board = new BoardResponseDto(entity.getBoard());
|
||||
if (this.board.getNewDisplayDayCount() != null) {
|
||||
this.isNew = createdDate.plusDays(this.board.getNewDisplayDayCount()).compareTo(LocalDateTime.now()) <= 0;
|
||||
} else {
|
||||
this.isNew = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 조회 수 증가
|
||||
*/
|
||||
public void increaseReadCount() {
|
||||
this.readCount = this.readCount + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 이전 게시물
|
||||
*/
|
||||
public void setPrevPosts(List<PostsSimpleResponseDto> prevPosts) {
|
||||
this.prevPosts = prevPosts;
|
||||
}
|
||||
|
||||
/**
|
||||
* 다음 게시물
|
||||
*/
|
||||
public void setNextPosts(List<PostsSimpleResponseDto> nextPosts) {
|
||||
this.nextPosts = nextPosts;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
package org.egovframe.cloud.boardservice.api.posts.dto;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.egovframe.cloud.boardservice.domain.board.Board;
|
||||
import org.egovframe.cloud.boardservice.domain.posts.Posts;
|
||||
import org.egovframe.cloud.boardservice.domain.posts.PostsId;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.boardservice.api.board.dto.PostsSaveRequestDto
|
||||
* <p>
|
||||
* 게시물 등록 요청 DTO 클래스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/07/28
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/07/28 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
public class PostsSaveRequestDto {
|
||||
|
||||
/**
|
||||
* 게시물 제목
|
||||
*/
|
||||
@NotBlank(message = "{posts.posts_title} {err.required}")
|
||||
private String postsTitle;
|
||||
|
||||
/**
|
||||
* 게시물 내용
|
||||
*/
|
||||
@NotBlank(message = "{posts.posts_content} {err.required}")
|
||||
private String postsContent;
|
||||
|
||||
/**
|
||||
* 게시물 답변 내용
|
||||
*/
|
||||
private String postsAnswerContent;
|
||||
|
||||
/**
|
||||
* 첨부파일 코드
|
||||
*/
|
||||
private String attachmentCode;
|
||||
|
||||
/**
|
||||
* 공지 여부
|
||||
*/
|
||||
@NotNull(message = "{posts.notice_at} {err.required}")
|
||||
private Boolean noticeAt;
|
||||
|
||||
/**
|
||||
* 게시물 등록 요청 DTO 클래스 생성자
|
||||
* 빌더 패턴으로 객체 생성
|
||||
*
|
||||
* @param postsTitle 게시물 제목
|
||||
* @param postsContent 게시물 내용
|
||||
* @param attachmentCode 첨부파일 코드
|
||||
* @param noticeAt 공지 여부
|
||||
*/
|
||||
@Builder
|
||||
public PostsSaveRequestDto(String postsTitle, String postsContent, String postsAnswerContent, String attachmentCode, Boolean noticeAt) {
|
||||
this.postsTitle = postsTitle;
|
||||
this.postsContent = postsContent;
|
||||
this.postsAnswerContent = postsAnswerContent;
|
||||
this.attachmentCode = attachmentCode;
|
||||
this.noticeAt = noticeAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물 등록 요청 DTO 속성 값으로 게시물 엔티티 빌더를 사용하여 객체 생성
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @return Posts 게시물 엔티티
|
||||
*/
|
||||
public Posts toEntity(Integer boardNo, Integer postsNo) {
|
||||
return Posts.builder()
|
||||
.board(Board.builder()
|
||||
.boardNo(boardNo)
|
||||
.build())
|
||||
.postsId(PostsId.builder()
|
||||
.boardNo(boardNo)
|
||||
.postsNo(postsNo)
|
||||
.build())
|
||||
.postsTitle(postsTitle)
|
||||
.postsContent(postsContent)
|
||||
.postsAnswerContent(postsAnswerContent)
|
||||
.attachmentCode(attachmentCode)
|
||||
.noticeAt(noticeAt)
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
package org.egovframe.cloud.boardservice.api.posts.dto;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import org.egovframe.cloud.boardservice.api.board.dto.BoardResponseDto;
|
||||
|
||||
import com.querydsl.core.annotations.QueryProjection;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.boardservice.api.posts.dto.PostsSimpleResponseDto
|
||||
* <p>
|
||||
* 게시물 응답 DTO 클래스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/09/03
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/09/03 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
public class PostsSimpleResponseDto implements Serializable {
|
||||
|
||||
/**
|
||||
* SerialVersionUID
|
||||
*/
|
||||
private static final long serialVersionUID = 6916914915364711614L;
|
||||
|
||||
/**
|
||||
* 게시판 번호
|
||||
*/
|
||||
private Integer boardNo;
|
||||
|
||||
/**
|
||||
* 게시물 번호
|
||||
*/
|
||||
private Integer postsNo;
|
||||
|
||||
/**
|
||||
* 게시물 제목
|
||||
*/
|
||||
private String postsTitle;
|
||||
|
||||
/**
|
||||
* 게시물 내용
|
||||
*/
|
||||
private String postsContent;
|
||||
|
||||
/**
|
||||
* 생성 일시
|
||||
*/
|
||||
private LocalDateTime createdDate;
|
||||
|
||||
/**
|
||||
* 신규 여부
|
||||
*/
|
||||
private Boolean isNew;
|
||||
|
||||
/**
|
||||
* 게시물 응답 DTO 생성자
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @param postsTitle 게시물 제목
|
||||
* @param postsContent 게시물 내용
|
||||
* @param createdDate 생성 일시
|
||||
*/
|
||||
@QueryProjection
|
||||
public PostsSimpleResponseDto(Integer boardNo, Integer postsNo,
|
||||
String postsTitle, String postsContent, LocalDateTime createdDate) {
|
||||
this.boardNo = boardNo;
|
||||
this.postsNo = postsNo;
|
||||
this.postsTitle = postsTitle;
|
||||
// this.postsContent = HtmlUtils.htmlEscape(HtmlUtils.htmlUnescape(postsContent)); // frontend 에서 처리
|
||||
this.postsContent = postsContent;
|
||||
this.createdDate = createdDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* 신규 여부 계산
|
||||
*
|
||||
* @param boardResponseDto 게시판 상세 응답 DTO
|
||||
* @return PostsSimpleResponseDto 게시물 응답 DTO
|
||||
*/
|
||||
public PostsSimpleResponseDto setIsNew(BoardResponseDto boardResponseDto) {
|
||||
if (boardResponseDto.getNewDisplayDayCount() != null) {
|
||||
this.isNew = createdDate.plusDays(boardResponseDto.getNewDisplayDayCount()).compareTo(LocalDateTime.now()) <= 0;
|
||||
} else {
|
||||
this.isNew = false;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package org.egovframe.cloud.boardservice.api.posts.dto;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.egovframe.cloud.boardservice.domain.board.Board;
|
||||
import org.egovframe.cloud.boardservice.domain.posts.Posts;
|
||||
import org.egovframe.cloud.boardservice.domain.posts.PostsId;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.boardservice.api.posts.dto.PostsSimpleSaveRequestDto
|
||||
*
|
||||
* 게시물 등록 요청 DTO 클래스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/09/10
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/09/10 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
public class PostsSimpleSaveRequestDto {
|
||||
|
||||
/**
|
||||
* 게시물 제목
|
||||
*/
|
||||
@NotBlank(message = "{posts.posts_title} {err.required}")
|
||||
private String postsTitle;
|
||||
|
||||
/**
|
||||
* 게시물 내용
|
||||
*/
|
||||
@NotBlank(message = "{posts.posts_content} {err.required}")
|
||||
private String postsContent;
|
||||
|
||||
/**
|
||||
* 첨부파일 코드
|
||||
*/
|
||||
private String attachmentCode;
|
||||
|
||||
/**
|
||||
* 게시물 등록 요청 DTO 클래스 생성자
|
||||
* 빌더 패턴으로 객체 생성
|
||||
*
|
||||
* @param postsTitle 게시물 제목
|
||||
* @param postsContent 게시물 내용
|
||||
* @param attachmentCode 첨부파일 코드
|
||||
*/
|
||||
@Builder
|
||||
public PostsSimpleSaveRequestDto(String postsTitle, String postsContent, String attachmentCode) {
|
||||
this.postsTitle = postsTitle;
|
||||
this.postsContent = postsContent;
|
||||
this.attachmentCode = attachmentCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물 등록 요청 DTO 속성 값으로 게시물 엔티티 빌더를 사용하여 객체 생성
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @return Posts 게시물 엔티티
|
||||
*/
|
||||
public Posts toEntity(Integer boardNo, Integer postsNo) {
|
||||
return Posts.builder()
|
||||
.board(Board.builder()
|
||||
.boardNo(boardNo)
|
||||
.build())
|
||||
.postsId(PostsId.builder()
|
||||
.boardNo(boardNo)
|
||||
.postsNo(postsNo)
|
||||
.build())
|
||||
.postsTitle(postsTitle)
|
||||
.postsContent(postsContent)
|
||||
.attachmentCode(attachmentCode)
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
package org.egovframe.cloud.boardservice.api.posts.dto;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.egovframe.cloud.boardservice.domain.posts.Posts;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.boardservice.api.board.dto.PostsUpdateRequestDto
|
||||
* <p>
|
||||
* 게시물 수정 요청 DTO 클래스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/07/08
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/07/08 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
public class PostsUpdateRequestDto {
|
||||
|
||||
/**
|
||||
* 게시물 제목
|
||||
*/
|
||||
@NotBlank(message = "{posts.posts_title} {err.required}")
|
||||
private String postsTitle;
|
||||
|
||||
/**
|
||||
* 게시물 내용
|
||||
*/
|
||||
@NotBlank(message = "{posts.posts_content} {err.required}")
|
||||
private String postsContent;
|
||||
|
||||
/**
|
||||
* 게시물 답변 내용
|
||||
*/
|
||||
private String postsAnswerContent;
|
||||
|
||||
/**
|
||||
* 첨부파일 코드
|
||||
*/
|
||||
private String attachmentCode;
|
||||
|
||||
/**
|
||||
* 공지 여부
|
||||
*/
|
||||
@NotNull(message = "{posts.notice_at} {err.required}")
|
||||
private Boolean noticeAt;
|
||||
|
||||
/**
|
||||
* 게시물 등록 요청 DTO 클래스 생성자
|
||||
* 빌더 패턴으로 객체 생성
|
||||
*
|
||||
* @param postsTitle 게시물 제목
|
||||
* @param postsContent 게시물 내용
|
||||
* @param postsAnswerContent 게시물 답변 내용
|
||||
* @param attachmentCode 첨부파일 코드
|
||||
* @param noticeAt 공지 여부
|
||||
*/
|
||||
@Builder
|
||||
public PostsUpdateRequestDto(String postsTitle, String postsContent, String postsAnswerContent, String attachmentCode, Boolean noticeAt) {
|
||||
this.postsTitle = postsTitle;
|
||||
this.postsContent = postsContent;
|
||||
this.postsAnswerContent = postsAnswerContent;
|
||||
this.attachmentCode = attachmentCode;
|
||||
this.noticeAt = noticeAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물 등록 요청 DTO 속성 값으로 게시물 엔티티 빌더를 사용하여 객체 생성
|
||||
*
|
||||
* @return Posts 게시물 엔티티
|
||||
*/
|
||||
public Posts toEntity() {
|
||||
return Posts.builder()
|
||||
.postsTitle(postsTitle)
|
||||
.postsContent(postsContent)
|
||||
.postsAnswerContent(postsAnswerContent)
|
||||
.attachmentCode(attachmentCode)
|
||||
.noticeAt(noticeAt)
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
package org.egovframe.cloud.boardservice.config;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.egovframe.cloud.servlet.config.AuthenticationFilter;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.boardservice.config.SecurityConfig
|
||||
* <p>
|
||||
* Spring Security Config 클래스
|
||||
* AuthenticationFilter 를 추가하고 토큰으로 setAuthentication 인증처리를 한다
|
||||
*
|
||||
* @author 표준프레임워크센터 jaeyeolkim
|
||||
* @version 1.0
|
||||
* @since 2021/06/30
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/06/30 jaeyeolkim 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@EnableWebSecurity // Spring Security 설정들을 활성화시켜 준다
|
||||
public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Value("${token.secret}")
|
||||
private String TOKEN_SECRET;
|
||||
|
||||
/**
|
||||
* 스프링 시큐리티 설정
|
||||
*
|
||||
* @param http
|
||||
* @throws Exception
|
||||
*/
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.csrf().disable()
|
||||
.headers().frameOptions().disable()
|
||||
.and()
|
||||
.sessionManagement()
|
||||
.sessionCreationPolicy(SessionCreationPolicy.STATELESS) // 토큰 사용하기 때문에 세션은 비활성화
|
||||
.and()
|
||||
.addFilter(getAuthenticationFilter());
|
||||
}
|
||||
|
||||
/**
|
||||
* 토큰에 담긴 정보로 Authentication 정보를 설정하여 jpa audit 처리에 사용된다.
|
||||
* 이 처리를 하지 않으면 AnonymousAuthenticationToken 으로 처리된다.
|
||||
*
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
private AuthenticationFilter getAuthenticationFilter() throws Exception {
|
||||
return new AuthenticationFilter(authenticationManager(), TOKEN_SECRET);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package org.egovframe.cloud.boardservice.config;
|
||||
|
||||
import com.querydsl.sql.MySQLTemplates;
|
||||
import com.querydsl.sql.SQLQueryFactory;
|
||||
import com.querydsl.sql.SQLTemplates;
|
||||
import com.querydsl.sql.spring.SpringConnectionProvider;
|
||||
import com.querydsl.sql.spring.SpringExceptionTranslator;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.common.config.SqlQueryConfig
|
||||
*
|
||||
* Native SQL 설정 클래스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/07/07
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/07/07 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@Configuration
|
||||
public class SqlQueryConfig {
|
||||
|
||||
/**
|
||||
* SQLQueryFactory 빈 등록
|
||||
*
|
||||
* @param dataSource 데이터 소스
|
||||
* @return SQLQueryFactory 쿼리 및 DML 절 생성을 위한 팩토리 클래스
|
||||
*/
|
||||
@Bean
|
||||
public SQLQueryFactory queryFactory(DataSource dataSource) {
|
||||
return new SQLQueryFactory(querydslConfiguration(), new SpringConnectionProvider(dataSource));
|
||||
}
|
||||
|
||||
/**
|
||||
* querydsl 설정
|
||||
*
|
||||
* @return Configuration 설정
|
||||
*/
|
||||
public com.querydsl.sql.Configuration querydslConfiguration() {
|
||||
SQLTemplates templates = MySQLTemplates.builder().build(); // MySQL
|
||||
com.querydsl.sql.Configuration configuration = new com.querydsl.sql.Configuration(templates);
|
||||
configuration.setExceptionTranslator(new SpringExceptionTranslator());
|
||||
return configuration;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,193 @@
|
||||
package org.egovframe.cloud.boardservice.domain.board;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.egovframe.cloud.servlet.domain.BaseEntity;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.boardservice.domain.board.Board
|
||||
* <p>
|
||||
* 게시판 엔티티 클래스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/07/26
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/07/26 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@Entity
|
||||
public class Board extends BaseEntity {
|
||||
|
||||
/**
|
||||
* 게시판 번호
|
||||
*/
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(columnDefinition = "int(9)")
|
||||
private Integer boardNo;
|
||||
|
||||
/**
|
||||
* 게시판 제목
|
||||
*/
|
||||
@Column(nullable = false, length = 100)
|
||||
private String boardName;
|
||||
|
||||
/**
|
||||
* 스킨 유형 코드
|
||||
*/
|
||||
@Column(nullable = false, length = 20)
|
||||
private String skinTypeCode;
|
||||
|
||||
/**
|
||||
* 제목 표시 길이
|
||||
*/
|
||||
@Column(nullable = false, columnDefinition = "mediumint(5) default '20'")
|
||||
private Integer titleDisplayLength;
|
||||
|
||||
/**
|
||||
* 게시물 표시 수
|
||||
*/
|
||||
@Column(nullable = false, columnDefinition = "mediumint(5) default '10'")
|
||||
private Integer postDisplayCount;
|
||||
|
||||
/**
|
||||
* 페이지 표시 수
|
||||
*/
|
||||
@Column(nullable = false, columnDefinition = "mediumint(5) default '10'")
|
||||
private Integer pageDisplayCount;
|
||||
|
||||
/**
|
||||
* 신규 표시 일 수
|
||||
*/
|
||||
@Column(nullable = false, columnDefinition = "mediumint(5) default '3'")
|
||||
private Integer newDisplayDayCount;
|
||||
|
||||
/**
|
||||
* 에디터 사용 여부
|
||||
*/
|
||||
@Column(nullable = false, columnDefinition = "tinyint(1) default '0'")
|
||||
private Boolean editorUseAt;
|
||||
|
||||
/**
|
||||
* 사용자 작성 여부
|
||||
*/
|
||||
@Column(nullable = false, columnDefinition = "tinyint(1) default '0'")
|
||||
private Boolean userWriteAt;
|
||||
|
||||
/**
|
||||
* 댓글 사용 여부
|
||||
*/
|
||||
@Column(nullable = false, columnDefinition = "tinyint(1) default '0'")
|
||||
private Boolean commentUseAt;
|
||||
|
||||
/**
|
||||
* 업로드 사용 여부
|
||||
*/
|
||||
@Column(nullable = false, columnDefinition = "tinyint(1) default '0'")
|
||||
private Boolean uploadUseAt;
|
||||
|
||||
/**
|
||||
* 업로드 제한 수
|
||||
*/
|
||||
@Column(columnDefinition = "mediumint(5)")
|
||||
private Integer uploadLimitCount;
|
||||
|
||||
/**
|
||||
* 업로드 제한 크기
|
||||
*/
|
||||
@Column(columnDefinition = "bigint(20)")
|
||||
private BigDecimal uploadLimitSize;
|
||||
|
||||
/**
|
||||
* 게시물 엔티티
|
||||
*/
|
||||
/*@OneToMany(mappedBy = "board", fetch = FetchType.LAZY)
|
||||
@OnDelete(action = OnDeleteAction.CASCADE)
|
||||
private List<Posts> posts;*/
|
||||
|
||||
/**
|
||||
* 빌더 패턴 클래스 생성자
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param boardName 게시판 명
|
||||
* @param skinTypeCode 스킨 유형 코드
|
||||
* @param titleDisplayLength 제목 표시 길이
|
||||
* @param postDisplayCount 게시물 표시 수
|
||||
* @param pageDisplayCount 페이지 표시 수
|
||||
* @param newDisplayDayCount 신규 표시 일 수
|
||||
* @param editorUseAt 에디터 사용 여부
|
||||
* @param userWriteAt 사용자 작성 여부
|
||||
* @param commentUseAt 댓글 사용 여부
|
||||
* @param uploadUseAt 업로드 사용 여부
|
||||
* @param uploadLimitCount 업로드 제한 수
|
||||
* @param uploadLimitSize 업로드 제한 크기
|
||||
*/
|
||||
@Builder
|
||||
public Board(Integer boardNo, String boardName, String skinTypeCode, Integer titleDisplayLength,
|
||||
Integer postDisplayCount, Integer pageDisplayCount, Integer newDisplayDayCount, Boolean editorUseAt,
|
||||
Boolean userWriteAt, Boolean commentUseAt, Boolean uploadUseAt, Integer uploadLimitCount,
|
||||
BigDecimal uploadLimitSize) {
|
||||
this.boardNo = boardNo;
|
||||
this.boardName = boardName;
|
||||
this.skinTypeCode = skinTypeCode;
|
||||
this.titleDisplayLength = titleDisplayLength;
|
||||
this.postDisplayCount = postDisplayCount;
|
||||
this.pageDisplayCount = pageDisplayCount;
|
||||
this.newDisplayDayCount = newDisplayDayCount;
|
||||
this.editorUseAt = editorUseAt;
|
||||
this.userWriteAt = userWriteAt;
|
||||
this.commentUseAt = commentUseAt;
|
||||
this.uploadUseAt = uploadUseAt;
|
||||
this.uploadLimitCount = uploadLimitCount;
|
||||
this.uploadLimitSize = uploadLimitSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시판 속성 값 수정
|
||||
*
|
||||
* @param boardName 게시판 명
|
||||
* @param skinTypeCode 스킨 유형 코드
|
||||
* @param titleDisplayLength 제목 표시 길이
|
||||
* @param postDisplayCount 게시물 표시 수
|
||||
* @param pageDisplayCount 페이지 표시 수
|
||||
* @param newDisplayDayCount 신규 표시 일 수
|
||||
* @param userWriteAt 사용자 작성 여부
|
||||
* @param editorUseAt 에디터 사용 여부
|
||||
* @param commentUseAt 댓글 사용 여부
|
||||
* @param uploadUseAt 업로드 사용 여부
|
||||
* @param uploadLimitCount 업로드 제한 수
|
||||
* @param uploadLimitSize 업로드 제한 크기
|
||||
* @return Board 게시판 엔티티
|
||||
*/
|
||||
public Board update(String boardName, String skinTypeCode, Integer titleDisplayLength, Integer postDisplayCount,
|
||||
Integer pageDisplayCount, Integer newDisplayDayCount, Boolean editorUseAt, Boolean userWriteAt,
|
||||
Boolean commentUseAt, Boolean uploadUseAt, Integer uploadLimitCount, BigDecimal uploadLimitSize) {
|
||||
this.boardName = boardName;
|
||||
this.skinTypeCode = skinTypeCode;
|
||||
this.titleDisplayLength = titleDisplayLength;
|
||||
this.postDisplayCount = postDisplayCount;
|
||||
this.pageDisplayCount = pageDisplayCount;
|
||||
this.newDisplayDayCount = newDisplayDayCount;
|
||||
this.editorUseAt = editorUseAt;
|
||||
this.userWriteAt = userWriteAt;
|
||||
this.commentUseAt = commentUseAt;
|
||||
this.uploadUseAt = uploadUseAt;
|
||||
this.uploadLimitCount = uploadLimitCount;
|
||||
this.uploadLimitSize = uploadLimitSize;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package org.egovframe.cloud.boardservice.domain.board;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.boardservice.domain.board.BoardRepository
|
||||
* <p>
|
||||
* 게시판 레파지토리 인터페이스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/07/26
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/07/26 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
public interface BoardRepository extends JpaRepository<Board, Integer>, BoardRepositoryCustom {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package org.egovframe.cloud.boardservice.domain.board;
|
||||
|
||||
import org.egovframe.cloud.boardservice.api.board.dto.BoardResponseDto;
|
||||
import org.egovframe.cloud.common.dto.RequestDto;
|
||||
import org.egovframe.cloud.boardservice.api.board.dto.BoardListResponseDto;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.boardservice.domain.board.BoardRepositoryCustom
|
||||
* <p>
|
||||
* 게시판 Querydsl 인터페이스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/07/26
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/07/26 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
public interface BoardRepositoryCustom {
|
||||
|
||||
/**
|
||||
* 게시판 페이지 목록 조회
|
||||
*
|
||||
* @param requestDto 게시판 목록 요청 DTO
|
||||
* @param pageable 페이지 정보
|
||||
* @return Page<BoardListResponseDto> 페이지 게시판 목록 응답 DTO
|
||||
*/
|
||||
Page<BoardListResponseDto> findPage(RequestDto requestDto, Pageable pageable);
|
||||
|
||||
/**
|
||||
* 게시판 목록 조회
|
||||
*
|
||||
* @param boardNos 게시판 번호 목록
|
||||
* @return List<BoardResponseDto> 게시판 상세 응답 DTO List
|
||||
*/
|
||||
List<BoardResponseDto> findAllByBoardNoIn(List<Integer> boardNos);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
package org.egovframe.cloud.boardservice.domain.board;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.egovframe.cloud.boardservice.api.board.dto.BoardListResponseDto;
|
||||
import org.egovframe.cloud.boardservice.api.board.dto.BoardResponseDto;
|
||||
import org.egovframe.cloud.boardservice.api.board.dto.QBoardListResponseDto;
|
||||
import org.egovframe.cloud.boardservice.api.board.dto.QBoardResponseDto;
|
||||
import org.egovframe.cloud.boardservice.domain.code.QCode;
|
||||
import org.egovframe.cloud.common.dto.RequestDto;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
||||
import com.google.common.base.CaseFormat;
|
||||
import com.querydsl.core.QueryResults;
|
||||
import com.querydsl.core.types.Order;
|
||||
import com.querydsl.core.types.OrderSpecifier;
|
||||
import com.querydsl.core.types.Path;
|
||||
import com.querydsl.core.types.dsl.BooleanExpression;
|
||||
import com.querydsl.core.types.dsl.Expressions;
|
||||
import com.querydsl.jpa.JPQLQuery;
|
||||
import com.querydsl.jpa.impl.JPAQueryFactory;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.boardservice.domain.board.BoardRepositoryImpl
|
||||
* <p>
|
||||
* 게시판 Querydsl 구현 클래스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/07/26
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/07/26 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class BoardRepositoryImpl implements BoardRepositoryCustom {
|
||||
|
||||
/**
|
||||
* DML 생성을위한 Querydsl 팩토리 클래스
|
||||
*/
|
||||
private final JPAQueryFactory jpaQueryFactory;
|
||||
|
||||
/**
|
||||
* 게시판 페이지 목록 조회
|
||||
* 가급적 Entity 보다는 Dto를 리턴 - Entity 조회시 hibernate 캐시, 불필요 컬럼 조회, oneToOne N+1 문제 발생
|
||||
*
|
||||
* @param requestDto 요청 DTO
|
||||
* @param pageable 페이지 정보
|
||||
* @return Page<BoardListResponseDto> 페이지 게시판 목록 응답 DTO
|
||||
*/
|
||||
@Override
|
||||
public Page<BoardListResponseDto> findPage(RequestDto requestDto, Pageable pageable) {
|
||||
JPQLQuery<BoardListResponseDto> query = jpaQueryFactory
|
||||
.select(new QBoardListResponseDto(
|
||||
QBoard.board.boardNo,
|
||||
QBoard.board.boardName,
|
||||
QBoard.board.skinTypeCode,
|
||||
Expressions.as(QCode.code.codeName, "skinTypeCodeName"),
|
||||
QBoard.board.createdDate
|
||||
))
|
||||
.from(QBoard.board)
|
||||
.leftJoin(QCode.code).on(QBoard.board.skinTypeCode.eq(QCode.code.codeId).and(QCode.code.parentCodeId.eq("skin_type_code")))
|
||||
.fetchJoin()
|
||||
.where(getBooleanExpressionKeyword(requestDto));
|
||||
|
||||
//정렬
|
||||
pageable.getSort().stream().forEach(sort -> {
|
||||
Order order = sort.isAscending() ? Order.ASC : Order.DESC;
|
||||
String property = sort.getProperty();
|
||||
|
||||
Path<Object> target = Expressions.path(Object.class, QBoard.board, CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, property));
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
OrderSpecifier<?> orderSpecifier = new OrderSpecifier(order, target);
|
||||
query.orderBy(orderSpecifier);
|
||||
});
|
||||
|
||||
QueryResults<BoardListResponseDto> result = query
|
||||
.offset(pageable.getOffset())
|
||||
.limit(pageable.getPageSize()) //페이징
|
||||
.fetchResults();
|
||||
|
||||
return new PageImpl<>(result.getResults(), pageable, result.getTotal());
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시판 목록 조회
|
||||
*
|
||||
* @param boardNos 게시판 번호 목록
|
||||
* @return List<BoardResponseDto> 게시판 상세 응답 DTO List
|
||||
*/
|
||||
@Override
|
||||
public List<BoardResponseDto> findAllByBoardNoIn(List<Integer> boardNos) {
|
||||
return jpaQueryFactory
|
||||
.select(new QBoardResponseDto(
|
||||
QBoard.board.boardNo,
|
||||
QBoard.board.boardName,
|
||||
QBoard.board.skinTypeCode,
|
||||
QBoard.board.titleDisplayLength,
|
||||
QBoard.board.postDisplayCount,
|
||||
QBoard.board.pageDisplayCount,
|
||||
QBoard.board.newDisplayDayCount,
|
||||
QBoard.board.editorUseAt,
|
||||
QBoard.board.userWriteAt,
|
||||
QBoard.board.commentUseAt,
|
||||
QBoard.board.uploadUseAt,
|
||||
QBoard.board.uploadLimitCount,
|
||||
QBoard.board.uploadLimitSize
|
||||
))
|
||||
.from(QBoard.board)
|
||||
.leftJoin(QCode.code).on(QBoard.board.skinTypeCode.eq(QCode.code.codeId).and(QCode.code.parentCodeId.eq("skin_type_code")))
|
||||
.fetchJoin()
|
||||
.where(QBoard.board.boardNo.in(boardNos))
|
||||
.orderBy(QBoard.board.boardNo.asc())
|
||||
.fetchResults().getResults();
|
||||
}
|
||||
|
||||
/**
|
||||
* 요청 DTO로 동적 검색 표현식 리턴
|
||||
*
|
||||
* @param requestDto 요청 DTO
|
||||
* @return BooleanExpression 검색 표현식
|
||||
*/
|
||||
private BooleanExpression getBooleanExpressionKeyword(RequestDto requestDto) {
|
||||
if (requestDto.getKeyword() == null || "".equals(requestDto.getKeyword())) return null;
|
||||
|
||||
switch (requestDto.getKeywordType()) {
|
||||
case "boardName": // 게시판 명
|
||||
return QBoard.board.boardName.containsIgnoreCase(requestDto.getKeyword());
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package org.egovframe.cloud.boardservice.domain.code;
|
||||
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.egovframe.cloud.servlet.domain.BaseEntity;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.boardservice.domain.code.Code
|
||||
* <p>
|
||||
* 공통코드 엔티티
|
||||
*
|
||||
* @author 표준프레임워크센터 jaeyeolkim
|
||||
* @version 1.0
|
||||
* @since 2021/07/12
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/07/12 jaeyeolkim 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@NoArgsConstructor
|
||||
@Entity
|
||||
public class Code extends BaseEntity {
|
||||
|
||||
@Id
|
||||
@Column(insertable = false, updatable = false)
|
||||
private String codeId; // 코드ID
|
||||
|
||||
@Column(insertable = false, updatable = false)
|
||||
private String parentCodeId; // 상위 코드ID
|
||||
|
||||
@Column(insertable = false, updatable = false)
|
||||
private String codeName; // 코드 명
|
||||
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
package org.egovframe.cloud.boardservice.domain.comment;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.egovframe.cloud.boardservice.domain.posts.Posts;
|
||||
import org.egovframe.cloud.boardservice.domain.user.User;
|
||||
import org.egovframe.cloud.servlet.domain.BaseEntity;
|
||||
import org.hibernate.annotations.DynamicInsert;
|
||||
import org.hibernate.annotations.DynamicUpdate;
|
||||
|
||||
import javax.persistence.*;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.boardservice.domain.comment.Comment
|
||||
* <p>
|
||||
* 댓글 엔티티 클래스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/08/04
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/08/04 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@DynamicInsert
|
||||
@DynamicUpdate
|
||||
@Entity
|
||||
public class Comment extends BaseEntity {
|
||||
|
||||
/**
|
||||
* 댓글 복합키
|
||||
*/
|
||||
@EmbeddedId
|
||||
private CommentId commentId;
|
||||
|
||||
/**
|
||||
* 댓글 내용
|
||||
*/
|
||||
@Column(nullable = false, length = 2000)
|
||||
private String commentContent;
|
||||
|
||||
/**
|
||||
* 그룹 번호
|
||||
*/
|
||||
@Column(columnDefinition = "int(9)")
|
||||
private Integer groupNo;
|
||||
|
||||
/**
|
||||
* 부모 댓글 번호
|
||||
*/
|
||||
@Column(columnDefinition = "int(9)")
|
||||
private Integer parentCommentNo;
|
||||
|
||||
/**
|
||||
* 깊이 순서
|
||||
*/
|
||||
@Column(nullable = false, columnDefinition = "smallint(3)")
|
||||
private Integer depthSeq;
|
||||
|
||||
/**
|
||||
* 정렬 순서
|
||||
*/
|
||||
@Column(nullable = false, columnDefinition = "int(9)")
|
||||
private Integer sortSeq;
|
||||
|
||||
/**
|
||||
* 삭제 여부
|
||||
*/
|
||||
@Column(nullable = false, columnDefinition = "tinyint(1) default '0'")
|
||||
private Integer deleteAt; // 0:미삭제, 1:작성자삭제, 2:관리자삭제
|
||||
|
||||
/**
|
||||
* 생성자 엔티티
|
||||
*/
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "createdBy", referencedColumnName = "userId", insertable = false, updatable = false)
|
||||
private User creator;
|
||||
|
||||
/**
|
||||
* 게시물 엔티티
|
||||
*/
|
||||
@MapsId("postsId") // CommentId.postsId 매핑
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumns({
|
||||
@JoinColumn(name = "board_no"),
|
||||
@JoinColumn(name = "posts_no")
|
||||
})
|
||||
private Posts posts;
|
||||
|
||||
/**
|
||||
* 빌더 패턴 클래스 생성자
|
||||
*
|
||||
* @param posts 게시물 엔티티
|
||||
* @param commentId 댓글 복합키
|
||||
* @param commentContent 게시물 내용
|
||||
* @param groupNo 그룹 번호
|
||||
* @param parentCommentNo 부모 댓글 번호
|
||||
* @param depthSeq 깊이 순서
|
||||
* @param sortSeq 정렬 순서
|
||||
* @param deleteAt 삭제 여부
|
||||
*/
|
||||
@Builder
|
||||
public Comment(Posts posts, CommentId commentId, String commentContent,
|
||||
Integer groupNo, Integer parentCommentNo, Integer depthSeq,
|
||||
Integer sortSeq, Integer deleteAt, User creator) {
|
||||
this.posts = posts;
|
||||
this.commentId = commentId;
|
||||
this.commentContent = commentContent;
|
||||
this.groupNo = groupNo;
|
||||
this.parentCommentNo = parentCommentNo;
|
||||
this.depthSeq = depthSeq;
|
||||
this.sortSeq = sortSeq;
|
||||
this.deleteAt = deleteAt;
|
||||
this.creator = creator;
|
||||
}
|
||||
|
||||
/**
|
||||
* 댓글 내용 수정
|
||||
*
|
||||
* @param commentContent 게시물 내용
|
||||
* @return Comment 댓글 엔티티
|
||||
*/
|
||||
public Comment update(String commentContent) {
|
||||
this.commentContent = commentContent;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 댓글 삭제 여부 수정
|
||||
*
|
||||
* @param deleteAt 삭제 여부
|
||||
* @return Comment 댓글 엔티티
|
||||
*/
|
||||
public Comment updateDeleteAt(Integer deleteAt) {
|
||||
this.deleteAt = deleteAt;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package org.egovframe.cloud.boardservice.domain.comment;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.egovframe.cloud.boardservice.domain.posts.PostsId;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Embeddable;
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.boardservice.domain.comment.CommentId
|
||||
* <p>
|
||||
* 댓글 엔티티 복합키 클래스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/08/04
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/08/04 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@Embeddable
|
||||
public class CommentId implements Serializable {
|
||||
|
||||
/**
|
||||
* serialVersionUID
|
||||
*/
|
||||
private static final long serialVersionUID = -8263227281325691911L;
|
||||
|
||||
/**
|
||||
* 게시물 복합키
|
||||
*/
|
||||
private PostsId postsId; // @MapsId("postsId")로 매핑
|
||||
|
||||
/**
|
||||
* 댓글 번호
|
||||
*/
|
||||
@Column(columnDefinition = "int(9)")
|
||||
private Integer commentNo;
|
||||
|
||||
/**
|
||||
* 빌드 패턴 클래스 생성자
|
||||
*
|
||||
* @param postsId 게시물 복합키
|
||||
* @param commentNo 댓글 번호
|
||||
*/
|
||||
@Builder
|
||||
public CommentId(PostsId postsId, Integer commentNo) {
|
||||
this.postsId = postsId;
|
||||
this.commentNo = commentNo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a hash code value for the object. This method is supported for the benefit of hash tables such as those provided by java.util.HashMap.
|
||||
*
|
||||
* @return int a hash code value for this object.
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(postsId.getBoardNo(), postsId.getPostsNo(), commentNo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether some other object is "equal to" this one.
|
||||
*
|
||||
* @param object the reference object with which to compare.
|
||||
* @return {@code true} if this object is the same as the obj
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
if (this == object) return true;
|
||||
if (!(object instanceof CommentId)) return false;
|
||||
CommentId that = (CommentId) object;
|
||||
return Objects.equals(postsId.getBoardNo(), that.getPostsId().getBoardNo()) &&
|
||||
Objects.equals(postsId.getPostsNo(), that.getPostsId().getPostsNo()) &&
|
||||
Objects.equals(commentNo, that.getCommentNo());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package org.egovframe.cloud.boardservice.domain.comment;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.boardservice.domain.comment.CommentRepository
|
||||
*
|
||||
* 댓글 레파지토리 인터페이스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/08/04
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/08/04 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
public interface CommentRepository extends JpaRepository<Comment, CommentId>, CommentRepositoryCustom {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
package org.egovframe.cloud.boardservice.domain.comment;
|
||||
|
||||
import org.egovframe.cloud.boardservice.api.comment.dto.CommentListResponseDto;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.boardservice.domain.comment.CommentRepositoryCustom
|
||||
* <p>
|
||||
* 댓글 Querydsl 인터페이스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/08/04
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/08/04 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
public interface CommentRepositoryCustom {
|
||||
|
||||
/**
|
||||
* 댓글 전체 목록 조회
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @param deleteAt 삭제 여부
|
||||
* @return List<CommentListResponseDto> 댓글 목록 응답 DTO
|
||||
*/
|
||||
List<CommentListResponseDto> findAll(Integer boardNo, Integer postsNo, Integer deleteAt);
|
||||
|
||||
/**
|
||||
* 댓글 목록 조회
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @param deleteAt 삭제 여부
|
||||
* @param pageable 페이지 정보
|
||||
* @return Map<String, Object> 페이지 댓글 목록 응답 DTO
|
||||
*/
|
||||
Map<String, Object> findPage(Integer boardNo, Integer postsNo, Integer deleteAt, Pageable pageable);
|
||||
|
||||
/**
|
||||
* 다음 댓글 번호 조회
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @return Integer 다음 댓글 번호
|
||||
*/
|
||||
Integer findNextCommentNo(Integer boardNo, Integer postsNo);
|
||||
|
||||
/**
|
||||
* 다음 정렬 순서 조회
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @return Integer 다음 댓글 번호
|
||||
*/
|
||||
Integer findNextSortSeq(Integer boardNo, Integer postsNo);
|
||||
|
||||
/**
|
||||
* 대댓글의 정렬 마지막 순서 조회
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @param groupNo 그룹 번호
|
||||
* @return Integer 다음 댓글 번호
|
||||
*/
|
||||
Integer findLastSortSeq(Integer boardNo, Integer postsNo, Integer groupNo);
|
||||
|
||||
/**
|
||||
* 대댓글의 정렬 순서 조회
|
||||
* 댓글그룹내에 부모 댓글 보다 정렬 순서가 크고 깊이가 크거나 같은 가장 작은 순서
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @param groupNo 그룹 번호
|
||||
* @param parentCommentNo 부모 게시물 번호
|
||||
* @param depthSeq 깊이 순서
|
||||
* @return Integer 다음 댓글 번호
|
||||
*/
|
||||
Integer findNextSortSeq(Integer boardNo, Integer postsNo, Integer groupNo, Integer parentCommentNo, Integer depthSeq);
|
||||
|
||||
/**
|
||||
* 댓글 삭제 여부 수정
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @param commentNo 댓글 번호
|
||||
* @param deleteAt 삭제 여부
|
||||
* @return Integer 처리 건수
|
||||
*/
|
||||
Long updateDeleteAt(Integer boardNo, Integer postsNo, Integer commentNo, Integer deleteAt);
|
||||
|
||||
/**
|
||||
* 댓글 정렬 순서 수정
|
||||
*
|
||||
* @param groupNo 그룹 번호
|
||||
* @param startSortSeq 시작 정렬 순서
|
||||
* @param endSortSeq 종료 정렬 순서
|
||||
* @param increaseSortSeq 증가 정렬 순서
|
||||
* @return Long 처리 건수
|
||||
*/
|
||||
Long updateSortSeq(Integer groupNo, Integer startSortSeq, Integer endSortSeq, int increaseSortSeq);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,362 @@
|
||||
package org.egovframe.cloud.boardservice.domain.comment;
|
||||
|
||||
import com.querydsl.core.Tuple;
|
||||
import com.querydsl.core.types.Path;
|
||||
import com.querydsl.core.types.SubQueryExpression;
|
||||
import com.querydsl.core.types.dsl.*;
|
||||
import com.querydsl.jpa.JPAExpressions;
|
||||
import com.querydsl.jpa.impl.JPAQueryFactory;
|
||||
import com.querydsl.sql.SQLQueryFactory;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.egovframe.cloud.boardservice.api.comment.dto.CommentListResponseDto;
|
||||
import org.egovframe.cloud.boardservice.api.comment.dto.QCommentListResponseDto;
|
||||
import org.egovframe.cloud.boardservice.domain.user.QUser;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.egovframe.cloud.boardservice.domain.comment.QComment.comment;
|
||||
import static org.egovframe.cloud.boardservice.domain.user.QUser.user;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.boardservice.domain.comment.CommentRepositoryImpl
|
||||
* <p>
|
||||
* 댓글 Querydsl 구현 클래스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/08/04
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/08/04 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class CommentRepositoryImpl implements CommentRepositoryCustom {
|
||||
|
||||
/**
|
||||
* DML 생성을위한 Querydsl 팩토리 클래스
|
||||
*/
|
||||
private final JPAQueryFactory jpaQueryFactory;
|
||||
|
||||
/**
|
||||
* 쿼리 및 DML 절 생성을 위한 팩토리 클래스
|
||||
*/
|
||||
private final SQLQueryFactory sqlQueryFactory;
|
||||
|
||||
|
||||
/**
|
||||
* 댓글 목록 조회
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @param deleteAt 삭제 여부
|
||||
* @return List<CommentListResponseDto> 댓글 목록 응답 DTO
|
||||
*/
|
||||
public List<CommentListResponseDto> findAll(Integer boardNo, Integer postsNo, Integer deleteAt) {
|
||||
return jpaQueryFactory
|
||||
.select(new QCommentListResponseDto(
|
||||
comment.commentId.postsId.boardNo,
|
||||
comment.commentId.postsId.postsNo,
|
||||
comment.commentId.commentNo,
|
||||
comment.commentContent,
|
||||
comment.groupNo,
|
||||
comment.parentCommentNo,
|
||||
comment.depthSeq,
|
||||
comment.sortSeq,
|
||||
comment.deleteAt,
|
||||
comment.createdBy,
|
||||
QUser.user.userName.as("createdName"),
|
||||
comment.createdDate))
|
||||
.from(comment)
|
||||
.leftJoin(user).on(comment.createdBy.eq(user.userId))
|
||||
.fetchJoin()
|
||||
.where(comment.commentId.postsId.boardNo.eq(boardNo)
|
||||
.and(comment.commentId.postsId.postsNo.eq(postsNo))
|
||||
.and(isEqualsDeleteAt(deleteAt)))
|
||||
.orderBy(comment.commentId.postsId.boardNo.asc(), comment.commentId.postsId.postsNo.asc(), comment.groupNo.asc(), comment.sortSeq.asc())
|
||||
.fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* 댓글 목록 조회
|
||||
* <p>
|
||||
* JPQL 은 from 절에서 서브쿼리를 사용할 수 없어서 SQLQueryFactory 를 사용해 Native SQL 로 조회
|
||||
* <p>
|
||||
* Native SQL 을 사용하지 않고 서브쿼리를 먼저 조회한 후 JPQL 만을 사용해서 조회 가능
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @param deleteAt 삭제 여부
|
||||
* @param pageable 페이지 정보
|
||||
* @return Map<String, Object> 페이지 댓글 목록 응답 DTO
|
||||
*/
|
||||
public Map<String, Object> findPage(Integer boardNo, Integer postsNo, Integer deleteAt, Pageable pageable) {
|
||||
// 전체 댓글 수, 최상위 댓글 수(페이징 기준) 조회
|
||||
String totalElementsKey = "totalElements";
|
||||
Tuple countInfo = jpaQueryFactory
|
||||
.select(Expressions.asNumber(1).count().as(totalElementsKey),
|
||||
new CaseBuilder()
|
||||
.when(comment.parentCommentNo.isNull())
|
||||
.then(1)
|
||||
.otherwise(0)
|
||||
.sum()
|
||||
.coalesce(0)
|
||||
.as("count"))
|
||||
.from(comment)
|
||||
.where(comment.commentId.postsId.boardNo.eq(boardNo)
|
||||
.and(comment.commentId.postsId.postsNo.eq(postsNo))
|
||||
.and(isEqualsDeleteAt(deleteAt)))
|
||||
.fetchOne();
|
||||
|
||||
Long totalElements = 0L;
|
||||
Integer groupElements = 0;
|
||||
if (countInfo != null) {
|
||||
totalElements = countInfo.get(Expressions.numberPath(Long.class, totalElementsKey)); // 전체 댓글 수
|
||||
groupElements = countInfo.get(Expressions.numberPath(Integer.class, "count")); // 최상위 댓글 수
|
||||
}
|
||||
|
||||
// path 정의
|
||||
Path<Comment> commentPath = Expressions.path(Comment.class, "comment");
|
||||
NumberPath<Integer> boardNoPath = Expressions.numberPath(Integer.class, commentPath, "board_no");
|
||||
NumberPath<Integer> postsNoPath = Expressions.numberPath(Integer.class, commentPath, "posts_no");
|
||||
NumberPath<Integer> commentNoPath = Expressions.numberPath(Integer.class, commentPath, "comment_no");
|
||||
NumberPath<Integer> groupNoPath = Expressions.numberPath(Integer.class, commentPath, "group_no");
|
||||
NumberPath<Integer> parentCommentNoPath = Expressions.numberPath(Integer.class, commentPath, "parent_comment_no");
|
||||
NumberPath<Integer> sortSeqPath = Expressions.numberPath(Integer.class, commentPath, "sort_seq");
|
||||
NumberPath<Integer> deleteAtPath = Expressions.numberPath(Integer.class, commentPath, "delete_at");
|
||||
|
||||
StringPath userPath = Expressions.stringPath("user");
|
||||
|
||||
BooleanExpression deleteAtExpression = null;
|
||||
if (deleteAt != null) {
|
||||
deleteAtExpression = deleteAt == 0 ? deleteAtPath.eq(0) : deleteAtPath.ne(0);
|
||||
}
|
||||
|
||||
// 댓글 그룹 조회
|
||||
Path<Comment> groupCommentPath = Expressions.path(Comment.class, "groupComment");
|
||||
SubQueryExpression<Tuple> groupComment = JPAExpressions.select(boardNoPath,
|
||||
postsNoPath,
|
||||
commentNoPath)
|
||||
.from(comment)
|
||||
.where(boardNoPath.eq(boardNo)
|
||||
.and(postsNoPath.eq(postsNo))
|
||||
.and(parentCommentNoPath.isNull())
|
||||
.and(deleteAtExpression))
|
||||
.orderBy(boardNoPath.asc(), postsNoPath.asc(), commentNoPath.asc())
|
||||
.offset(pageable.getOffset())
|
||||
.limit(pageable.getPageSize());
|
||||
|
||||
// 댓글 조회
|
||||
List<CommentListResponseDto> comments = sqlQueryFactory
|
||||
.select(new QCommentListResponseDto(
|
||||
boardNoPath,
|
||||
postsNoPath,
|
||||
commentNoPath,
|
||||
Expressions.stringPath(commentPath, "comment_content"),
|
||||
groupNoPath,
|
||||
parentCommentNoPath,
|
||||
Expressions.numberPath(Integer.class, commentPath, "depth_seq"),
|
||||
Expressions.numberPath(Integer.class, commentPath, "sort_seq"),
|
||||
Expressions.numberPath(Integer.class, commentPath, "delete_at"),
|
||||
Expressions.stringPath(commentPath, "created_by"),
|
||||
Expressions.stringPath(userPath, "user_name"),
|
||||
Expressions.datePath(LocalDateTime.class, commentPath, "created_date")))
|
||||
.from(comment)
|
||||
.innerJoin(groupComment, groupCommentPath).on(Expressions.numberPath(Integer.class, groupCommentPath, "board_no").eq(boardNoPath)
|
||||
.and(Expressions.numberPath(Integer.class, groupCommentPath, "posts_no").eq(postsNoPath))
|
||||
.and(Expressions.numberPath(Integer.class, groupCommentPath, "comment_no").eq(groupNoPath)))
|
||||
.leftJoin(user).on(Expressions.stringPath(commentPath, "created_by").eq(Expressions.stringPath(userPath, "user_id")))
|
||||
.where(boardNoPath.eq(boardNo)
|
||||
.and(postsNoPath.eq(postsNo))
|
||||
.and(deleteAtExpression))
|
||||
.orderBy(boardNoPath.asc(), postsNoPath.asc(), groupNoPath.asc(), sortSeqPath.asc())
|
||||
.fetch();
|
||||
|
||||
Page<CommentListResponseDto> page = new PageImpl<>(comments, pageable, groupElements == null ? 0 : groupElements);
|
||||
|
||||
// 페이지 인터페이스와 동일한 속성의 맵 리턴
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
|
||||
result.put("content", comments);
|
||||
result.put("empty", page.isEmpty());
|
||||
result.put("first", page.isFirst());
|
||||
result.put("last", page.isLast());
|
||||
result.put("number", page.getNumber());
|
||||
result.put("numberOfElements", comments.size());
|
||||
result.put("size", page.getSize());
|
||||
result.put(totalElementsKey, totalElements);
|
||||
result.put("groupElements", groupElements);
|
||||
result.put("totalPages", page.getTotalPages());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 다음 댓글 번호 조회
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @return Integer 다음 게시물 번호
|
||||
*/
|
||||
public Integer findNextCommentNo(Integer boardNo, Integer postsNo) {
|
||||
return jpaQueryFactory
|
||||
.select(comment.commentId.commentNo.max().add(1).coalesce(1))
|
||||
.from(comment)
|
||||
.where(comment.commentId.postsId.boardNo.eq(boardNo)
|
||||
.and(comment.commentId.postsId.postsNo.eq(postsNo)))
|
||||
.fetchOne();
|
||||
}
|
||||
|
||||
/**
|
||||
* 다음 정렬 순서 조회
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @return Integer 다음 게시물 번호
|
||||
*/
|
||||
public Integer findNextSortSeq(Integer boardNo, Integer postsNo) {
|
||||
return jpaQueryFactory
|
||||
.select(comment.sortSeq.max().add(1).coalesce(1))
|
||||
.from(comment)
|
||||
.where(comment.commentId.postsId.boardNo.eq(boardNo)
|
||||
.and(comment.commentId.postsId.postsNo.eq(postsNo))
|
||||
.and(comment.parentCommentNo.isNull()))
|
||||
.fetchOne();
|
||||
}
|
||||
|
||||
/**
|
||||
* 대댓글의 정렬 마지막 순서 조회
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @param groupNo 그룹 번호
|
||||
* @return Integer 다음 게시물 번호
|
||||
*/
|
||||
public Integer findLastSortSeq(Integer boardNo, Integer postsNo, Integer groupNo) {
|
||||
return jpaQueryFactory
|
||||
.select(comment.sortSeq.max().add(1).coalesce(1))
|
||||
.from(comment)
|
||||
.where(comment.commentId.postsId.boardNo.eq(boardNo)
|
||||
.and(comment.commentId.postsId.postsNo.eq(postsNo))
|
||||
.and(comment.groupNo.eq(groupNo)))
|
||||
.fetchOne();
|
||||
}
|
||||
|
||||
/**
|
||||
* 대댓글의 정렬 순서 조회
|
||||
* 댓글그룹내에 부모 댓글 보다 정렬 순서가 크고 깊이가 크거나 같은 가장 작은 순서
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @param groupNo 그룹 번호
|
||||
* @param parentCommentNo 부모 게시물 번호
|
||||
* @param depthSeq 깊이 순서
|
||||
* @return Integer 다음 게시물 번호
|
||||
*/
|
||||
public Integer findNextSortSeq(Integer boardNo, Integer postsNo, Integer groupNo, Integer parentCommentNo, Integer depthSeq) {
|
||||
return jpaQueryFactory
|
||||
.select(comment.sortSeq.min())
|
||||
.from(comment)
|
||||
.where(comment.commentId.postsId.boardNo.eq(boardNo)
|
||||
.and(comment.commentId.postsId.postsNo.eq(postsNo))
|
||||
.and(comment.groupNo.eq(groupNo))
|
||||
.and(comment.sortSeq.gt(JPAExpressions.select(comment.sortSeq)
|
||||
.from(comment)
|
||||
.where(comment.commentId.postsId.boardNo.eq(boardNo)
|
||||
.and(comment.commentId.postsId.postsNo.eq(postsNo))
|
||||
.and(comment.commentId.commentNo.eq(parentCommentNo)))))
|
||||
.and(comment.depthSeq.lt(depthSeq)))
|
||||
.fetchOne();
|
||||
}
|
||||
|
||||
/**
|
||||
* 댓글 정렬 순서 수정
|
||||
*
|
||||
* @param groupNo 그룹 번호
|
||||
* @param startSortSeq 시작 정렬 순서
|
||||
* @param endSortSeq 종료 정렬 순서
|
||||
* @param increaseSortSeq 증가 정렬 순서
|
||||
* @return Long 수정 건수
|
||||
*/
|
||||
public Long updateSortSeq(Integer groupNo, Integer startSortSeq, Integer endSortSeq, int increaseSortSeq) {
|
||||
return jpaQueryFactory.update(comment)
|
||||
.set(comment.sortSeq, comment.sortSeq.add(increaseSortSeq))
|
||||
.where(isEqualsGroupNo(groupNo),
|
||||
isGoeSortSeq(startSortSeq),
|
||||
isLoeSortSeq(endSortSeq))
|
||||
.execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* 댓글 삭제 여부 수정
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @param commentNo 댓글 번호
|
||||
* @param deleteAt 삭제 여부
|
||||
* @return Integer 처리 건수
|
||||
*/
|
||||
public Long updateDeleteAt(Integer boardNo, Integer postsNo, Integer commentNo, Integer deleteAt) {
|
||||
return jpaQueryFactory.update(comment)
|
||||
.set(comment.deleteAt, deleteAt)
|
||||
.set(comment.modifiedDate, LocalDateTime.now())
|
||||
.where(comment.commentId.postsId.boardNo.eq(boardNo)
|
||||
.and(comment.commentId.postsId.postsNo.eq(postsNo))
|
||||
.and(comment.commentId.commentNo.eq(commentNo)))
|
||||
.execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* 삭제여부 검색 표현식
|
||||
*
|
||||
* @param deleteAt 삭제 여부
|
||||
* @return BooleanExpression 검색 표현식
|
||||
*/
|
||||
private BooleanExpression isEqualsDeleteAt(Integer deleteAt) {
|
||||
if (deleteAt == null) return null;
|
||||
|
||||
if (deleteAt == 0) return comment.deleteAt.eq(deleteAt);
|
||||
else return comment.deleteAt.ne(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 그룹 번호 동일 검색 표현식
|
||||
*
|
||||
* @param groupNo 그룹 번호
|
||||
* @return BooleanExpression 검색 표현식
|
||||
*/
|
||||
private BooleanExpression isEqualsGroupNo(Integer groupNo) {
|
||||
return groupNo == null ? null : comment.groupNo.eq(groupNo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 정렬 순서 이하 검색 표현식
|
||||
*
|
||||
* @param sortSeq 정렬 순서
|
||||
* @return BooleanExpression 검색 표현식
|
||||
*/
|
||||
private BooleanExpression isLoeSortSeq(Integer sortSeq) {
|
||||
return sortSeq == null ? null : comment.sortSeq.loe(sortSeq);
|
||||
}
|
||||
|
||||
/**
|
||||
* 정렬 순서 이상 검색 표현식
|
||||
*
|
||||
* @param sortSeq 정렬 순서
|
||||
* @return BooleanExpression 검색 표현식
|
||||
*/
|
||||
private BooleanExpression isGoeSortSeq(Integer sortSeq) {
|
||||
return sortSeq == null ? null : comment.sortSeq.goe(sortSeq);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
package org.egovframe.cloud.boardservice.domain.posts;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.egovframe.cloud.boardservice.domain.board.Board;
|
||||
import org.egovframe.cloud.boardservice.domain.comment.Comment;
|
||||
import org.egovframe.cloud.boardservice.domain.user.User;
|
||||
import org.egovframe.cloud.servlet.domain.BaseEntity;
|
||||
import org.hibernate.annotations.DynamicInsert;
|
||||
import org.hibernate.annotations.DynamicUpdate;
|
||||
import org.hibernate.annotations.OnDelete;
|
||||
import org.hibernate.annotations.OnDeleteAction;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.boardservice.domain.posts.Posts
|
||||
* <p>
|
||||
* 게시물 엔티티 클래스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/07/28
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/07/28 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@DynamicInsert
|
||||
@DynamicUpdate
|
||||
@Entity
|
||||
public class Posts extends BaseEntity {
|
||||
|
||||
/**
|
||||
* 게시물 복합키
|
||||
*/
|
||||
@EmbeddedId
|
||||
private PostsId postsId;
|
||||
|
||||
/**
|
||||
* 게시판 엔티티
|
||||
*/
|
||||
@MapsId("boardNo") // PostsId.boardNo 매핑
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "board_no")
|
||||
private Board board;
|
||||
|
||||
/**
|
||||
* 게시물 제목
|
||||
*/
|
||||
@Column(nullable = false, length = 100)
|
||||
private String postsTitle;
|
||||
|
||||
/**
|
||||
* 게시물 내용
|
||||
*/
|
||||
@Column(nullable = false, columnDefinition = "longtext")
|
||||
private String postsContent;
|
||||
|
||||
/**
|
||||
* 게시물 내용
|
||||
*/
|
||||
@Column(columnDefinition = "longtext")
|
||||
private String postsAnswerContent;
|
||||
|
||||
/**
|
||||
* 첨부파일 코드
|
||||
*/
|
||||
@Column
|
||||
private String attachmentCode;
|
||||
|
||||
/**
|
||||
* 조회 수
|
||||
*/
|
||||
@Column(columnDefinition = "int(9) default '0'")
|
||||
private Integer readCount;
|
||||
|
||||
/**
|
||||
* 공지 여부
|
||||
*/
|
||||
@Column(nullable = false, columnDefinition = "tinyint(1) default '0'")
|
||||
private Boolean noticeAt;
|
||||
|
||||
/**
|
||||
* 삭제 여부
|
||||
*/
|
||||
@Column(nullable = false, columnDefinition = "tinyint(1) default '0'")
|
||||
private Integer deleteAt;
|
||||
|
||||
/**
|
||||
* 생성자 엔티티
|
||||
*/
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "createdBy", referencedColumnName = "userId", insertable = false, updatable = false)
|
||||
private User creator;
|
||||
|
||||
/**
|
||||
* 댓글 엔티티
|
||||
*/
|
||||
@OneToMany(mappedBy = "posts", fetch = FetchType.LAZY)
|
||||
@OnDelete(action = OnDeleteAction.CASCADE)
|
||||
private List<Comment> comments;
|
||||
|
||||
/**
|
||||
* 빌더 패턴 클래스 생성자
|
||||
*
|
||||
* @param board 게시판 엔티티
|
||||
* @param postsId 게시물 복합키
|
||||
* @param postsTitle 게시물 제목
|
||||
* @param postsContent 게시물 내용
|
||||
* @param postsAnswerContent 게시물 답변 내용
|
||||
* @param attachmentCode 첨부파일 코드
|
||||
* @param readCount 조회 수
|
||||
* @param noticeAt 공지 여부
|
||||
* @param deleteAt 삭제 여부
|
||||
*/
|
||||
@Builder
|
||||
public Posts(Board board, PostsId postsId, String postsTitle,
|
||||
String postsContent, String postsAnswerContent, String attachmentCode,
|
||||
Integer readCount, Boolean noticeAt, Integer deleteAt,
|
||||
User creator, List<Comment> comments) {
|
||||
this.board = board;
|
||||
this.postsId = postsId;
|
||||
this.postsTitle = postsTitle;
|
||||
this.postsContent = postsContent;
|
||||
this.postsAnswerContent = postsAnswerContent;
|
||||
this.attachmentCode = attachmentCode;
|
||||
this.readCount = readCount;
|
||||
this.noticeAt = noticeAt;
|
||||
this.deleteAt = deleteAt;
|
||||
this.creator = creator;
|
||||
this.comments = comments;
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물 속성 값 수정
|
||||
*
|
||||
* @param postsTitle 게시물 제목
|
||||
* @param postsContent 게시물 내용
|
||||
* @param attachmentCode 첨부파일 코드
|
||||
* @return Posts 게시물 엔티티
|
||||
*/
|
||||
public Posts update(String postsTitle, String postsContent, String attachmentCode) {
|
||||
this.postsTitle = postsTitle;
|
||||
this.postsContent = postsContent;
|
||||
this.attachmentCode = attachmentCode;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물 속성 값 수정
|
||||
*
|
||||
* @param postsTitle 게시물 제목
|
||||
* @param postsContent 게시물 내용
|
||||
* @param postsAnswerContent 게시물 답변 내용
|
||||
* @param attachmentCode 첨부파일 코드
|
||||
* @param noticeAt 공지 여부
|
||||
* @return Posts 게시물 엔티티
|
||||
*/
|
||||
public Posts update(String postsTitle, String postsContent, String postsAnswerContent, String attachmentCode, Boolean noticeAt) {
|
||||
this.postsTitle = postsTitle;
|
||||
this.postsContent = postsContent;
|
||||
this.postsAnswerContent = postsAnswerContent;
|
||||
this.attachmentCode = attachmentCode;
|
||||
this.noticeAt = noticeAt;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물 삭제 여부 수정
|
||||
*
|
||||
* @param deleteAt 삭제 여부
|
||||
* @return Posts 게시물 엔티티
|
||||
*/
|
||||
public Posts updateDeleteAt(Integer deleteAt) {
|
||||
this.deleteAt = deleteAt;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 조회 수 증가
|
||||
*
|
||||
* @return Posts 게시물 엔티티
|
||||
*/
|
||||
public Posts updateReadCount() {
|
||||
this.readCount += 1;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package org.egovframe.cloud.boardservice.domain.posts;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Embeddable;
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.boardservice.domain.posts.PostsId
|
||||
* <p>
|
||||
* 게시물 엔티티 복합키 클래스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/07/30
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/07/30 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@Embeddable
|
||||
public class PostsId implements Serializable {
|
||||
|
||||
/**
|
||||
* serialVersionUID
|
||||
*/
|
||||
private static final long serialVersionUID = 2286680637185590124L;
|
||||
|
||||
/**
|
||||
* 게시판 번호
|
||||
*/
|
||||
@Column(columnDefinition = "int(9)")
|
||||
private Integer boardNo; // @MapsId("boardNo")로 매핑
|
||||
|
||||
/**
|
||||
* 게시물 번호
|
||||
*/
|
||||
@Column(columnDefinition = "int(9)")
|
||||
private Integer postsNo;
|
||||
|
||||
/**
|
||||
* 빌드 패턴 클래스 생성자
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
*/
|
||||
@Builder
|
||||
public PostsId(Integer boardNo, Integer postsNo) {
|
||||
this.boardNo = boardNo;
|
||||
this.postsNo = postsNo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a hash code value for the object. This method is supported for the benefit of hash tables such as those provided by java.util.HashMap.
|
||||
*
|
||||
* @return int a hash code value for this object.
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(boardNo, postsNo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether some other object is "equal to" this one.
|
||||
*
|
||||
* @param object the reference object with which to compare.
|
||||
* @return {@code true} if this object is the same as the obj
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
if (this == object) return true;
|
||||
if (!(object instanceof PostsId)) return false;
|
||||
PostsId that = (PostsId) object;
|
||||
return Objects.equals(boardNo, that.getBoardNo()) &&
|
||||
Objects.equals(postsNo, that.getPostsNo());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.boardNo+"_"+this.postsNo;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package org.egovframe.cloud.boardservice.domain.posts;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.data.annotation.CreatedDate;
|
||||
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.EmbeddedId;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EntityListeners;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.boardservice.domain.posts.PostsRead
|
||||
* <p>
|
||||
* 게시물 조회 엔티티 클래스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/08/02
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/08/02 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@Entity
|
||||
@EntityListeners(AuditingEntityListener.class) // Auditing 기능 포함
|
||||
public class PostsRead {
|
||||
|
||||
/**
|
||||
* 게시물 조회 복합키
|
||||
*/
|
||||
@EmbeddedId
|
||||
private PostsReadId postsReadId;
|
||||
|
||||
/**
|
||||
* 사용자 id
|
||||
*/
|
||||
private String userId;
|
||||
|
||||
/**
|
||||
* ip 주소
|
||||
*/
|
||||
@Column(nullable = false, columnDefinition = "varchar(50)")
|
||||
private String ipAddr;
|
||||
|
||||
/**
|
||||
* 생성 일시
|
||||
*/
|
||||
@CreatedDate
|
||||
@Column
|
||||
private LocalDateTime createdDate;
|
||||
|
||||
/**
|
||||
* 빌더 패턴 클래스 생성자
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @param readNo 조회 번호
|
||||
* @param userId 사용자 id
|
||||
* @param tokenId 토큰 id
|
||||
* @param ipAddr ip 주소
|
||||
*/
|
||||
@Builder
|
||||
public PostsRead(Integer boardNo, Integer postsNo, Integer readNo, String userId, String tokenId, String ipAddr) {
|
||||
this.postsReadId = PostsReadId.builder()
|
||||
.boardNo(boardNo)
|
||||
.postsNo(postsNo)
|
||||
.readNo(readNo)
|
||||
.build();
|
||||
this.userId = userId;
|
||||
this.ipAddr = ipAddr;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package org.egovframe.cloud.boardservice.domain.posts;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Embeddable;
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.boardservice.domain.posts.PostsReadId
|
||||
* <p>
|
||||
* 게시판 조회 엔티티 복합키 클래스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/08/02
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/08/02 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@Embeddable
|
||||
public class PostsReadId implements Serializable {
|
||||
|
||||
/**
|
||||
* serialVersionUID
|
||||
*/
|
||||
private static final long serialVersionUID = -6710005976442877773L;
|
||||
|
||||
/**
|
||||
* 게시판 번호
|
||||
*/
|
||||
@Column(columnDefinition = "int(9)")
|
||||
private Integer boardNo;
|
||||
|
||||
/**
|
||||
* 게시물 번호
|
||||
*/
|
||||
@Column(columnDefinition = "int(9)")
|
||||
private Integer postsNo;
|
||||
|
||||
/**
|
||||
* 조회 번호
|
||||
*/
|
||||
@Column(columnDefinition = "int(9)")
|
||||
private Integer readNo;
|
||||
|
||||
/**
|
||||
* 빌드 패턴 클래스 생성자
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @param readNo 조회 번호
|
||||
*/
|
||||
@Builder
|
||||
public PostsReadId(Integer boardNo, Integer postsNo, Integer readNo) {
|
||||
this.boardNo = boardNo;
|
||||
this.postsNo = postsNo;
|
||||
this.readNo = readNo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a hash code value for the object. This method is supported for the benefit of hash tables such as those provided by java.util.HashMap.
|
||||
*
|
||||
* @return int a hash code value for this object.
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(boardNo, postsNo, readNo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether some other object is "equal to" this one.
|
||||
*
|
||||
* @param object the reference object with which to compare.
|
||||
* @return {@code true} if this object is the same as the obj
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
if (this == object) return true;
|
||||
if (!(object instanceof PostsReadId)) return false;
|
||||
PostsReadId that = (PostsReadId) object;
|
||||
return Objects.equals(boardNo, that.getBoardNo()) &&
|
||||
Objects.equals(postsNo, that.getPostsNo()) &&
|
||||
Objects.equals(readNo, that.getReadNo());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package org.egovframe.cloud.boardservice.domain.posts;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.boardservice.domain.posts.PostsReadRepository
|
||||
* <p>
|
||||
* 게시물 조회 레파지토리 인터페이스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/08/02
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/08/02 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
public interface PostsReadRepository extends JpaRepository<PostsRead, PostsReadId>, PostsReadRepositoryCustom {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package org.egovframe.cloud.boardservice.domain.posts;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.boardservice.domain.posts.PostsReadRepositoryCustom
|
||||
* <p>
|
||||
* 게시물 조회 Querydsl 인터페이스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/08/02
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/08/02 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
public interface PostsReadRepositoryCustom {
|
||||
|
||||
/**
|
||||
* 게시물 조회 데이터 수 조회
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @param userId 사용자 id
|
||||
* @param ipAddr ip 주소
|
||||
* @return Long 데이터 수
|
||||
*/
|
||||
Long countByBoardNoAndPostsNoAndUserId(Integer boardNo, Integer postsNo, String userId, String ipAddr);
|
||||
|
||||
/**
|
||||
* 다음 게시물 조회 번호 조회
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @return Integer 다음 게시물 조회 번호
|
||||
*/
|
||||
Integer findNextReadNo(Integer boardNo, Integer postsNo);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
package org.egovframe.cloud.boardservice.domain.posts;
|
||||
|
||||
import com.querydsl.core.types.dsl.BooleanExpression;
|
||||
import com.querydsl.jpa.impl.JPAQueryFactory;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.boardservice.domain.posts.PostsReadRepositoryImpl
|
||||
* <p>
|
||||
* 게시물 조회 Querydsl 구현 클래스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/08/02
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/08/02 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class PostsReadRepositoryImpl implements PostsReadRepositoryCustom {
|
||||
|
||||
/**
|
||||
* DML 생성을위한 Querydsl 팩토리 클래스
|
||||
*/
|
||||
private final JPAQueryFactory jpaQueryFactory;
|
||||
|
||||
/**
|
||||
* 게시물 조회 데이터 수 조회
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @param userId 사용자 id
|
||||
* @param ipAddr ip 주소
|
||||
* @return Long 데이터 수
|
||||
*/
|
||||
public Long countByBoardNoAndPostsNoAndUserId(Integer boardNo, Integer postsNo, String userId, String ipAddr) {
|
||||
return jpaQueryFactory
|
||||
.selectFrom(QPostsRead.postsRead)
|
||||
.where(QPostsRead.postsRead.postsReadId.boardNo.eq(boardNo)
|
||||
.and(QPostsRead.postsRead.postsReadId.postsNo.eq(postsNo))
|
||||
.and(getBooleanExpression("userId", userId))
|
||||
.and(getBooleanExpression("ipAddr", ipAddr)))
|
||||
.fetchCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* 다음 게시물 조회 번호 조회
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @return Integer 다음 게시물 조회 번호
|
||||
*/
|
||||
public Integer findNextReadNo(Integer boardNo, Integer postsNo) {
|
||||
return jpaQueryFactory.select(QPostsRead.postsRead.postsReadId.readNo.max().add(1).coalesce(1))
|
||||
.from(QPostsRead.postsRead)
|
||||
.where(QPostsRead.postsRead.postsReadId.boardNo.eq(boardNo)
|
||||
.and(QPostsRead.postsRead.postsReadId.postsNo.eq(postsNo)))
|
||||
.fetchOne();
|
||||
}
|
||||
|
||||
/**
|
||||
* 엔티티 속성별 동적 검색 표현식 리턴
|
||||
*
|
||||
* @param attributeName 속성 명
|
||||
* @param attributeValue 속성 값
|
||||
* @return BooleanExpression 검색 표현식
|
||||
*/
|
||||
private BooleanExpression getBooleanExpression(String attributeName, Object attributeValue) {
|
||||
if (attributeValue == null || "".equals(attributeValue.toString())) return null;
|
||||
|
||||
switch (attributeName) {
|
||||
case "userId": // 사용자 id
|
||||
return QPostsRead.postsRead.userId.eq((String) attributeValue);
|
||||
case "ipAddr": // ip 주소
|
||||
return QPostsRead.postsRead.ipAddr.eq((String) attributeValue);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package org.egovframe.cloud.boardservice.domain.posts;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.boardservice.domain.posts.PostsRepository
|
||||
* <p>
|
||||
* 게시물 레파지토리 인터페이스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/07/28
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/07/28 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
public interface PostsRepository extends JpaRepository<Posts, PostsId>, PostsRepositoryCustom {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
package org.egovframe.cloud.boardservice.domain.posts;
|
||||
|
||||
import org.egovframe.cloud.boardservice.api.posts.dto.PostsListResponseDto;
|
||||
import org.egovframe.cloud.boardservice.api.posts.dto.PostsResponseDto;
|
||||
import org.egovframe.cloud.boardservice.api.posts.dto.PostsSimpleResponseDto;
|
||||
import org.egovframe.cloud.common.dto.RequestDto;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.boardservice.domain.posts.PostsRepositoryCustom
|
||||
* <p>
|
||||
* 게시물 Querydsl 인터페이스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/07/28
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/07/28 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
public interface PostsRepositoryCustom {
|
||||
|
||||
/**
|
||||
* 게시물 페이지 목록 조회
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param deleteAt 삭제 여부
|
||||
* @param requestDto 요청 DTO
|
||||
* @param pageable 페이지 정보
|
||||
* @return Page<PostsListResponseDto> 페이지 게시물 목록 응답 DTO
|
||||
*/
|
||||
Page<PostsListResponseDto> findPage(Integer boardNo, Integer deleteAt, RequestDto requestDto, Pageable pageable);
|
||||
|
||||
/**
|
||||
* 게시판별 최근 게시물 목록 조회
|
||||
*
|
||||
* @param boardNos 게시판 번호 목록
|
||||
* @param postsCount 게시물 수
|
||||
* @return List<PostsSimpleResponseDto> 게시물 응답 DTO List
|
||||
*/
|
||||
List<PostsSimpleResponseDto> findAllByBoardNosLimitCount(List<Integer> boardNos, Integer postsCount);
|
||||
|
||||
/**
|
||||
* 게시물 상세 조회
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @param userId 사용자 id
|
||||
* @param ipAddr ip 주소
|
||||
* @return PostsResponseDto 게시물 상세 응답 DTO
|
||||
*/
|
||||
PostsResponseDto findById(Integer boardNo, Integer postsNo, String userId, String ipAddr);
|
||||
|
||||
/**
|
||||
* 근처 게시물 조회
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @param gap 차이 -1: 이전, 1: 이후
|
||||
* @param deleteAt 삭제 여부
|
||||
* @param requestDto 요청 DTO
|
||||
* @return List<PostsSimpleResponseDto> 게시물 상세 응답 DTO List
|
||||
*/
|
||||
List<PostsSimpleResponseDto> findNearPost(Integer boardNo, Integer postsNo, long gap, Integer deleteAt, RequestDto requestDto);
|
||||
|
||||
/**
|
||||
* 다음 게시물 번호 조회
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @return Integer 다음 게시물 번호
|
||||
*/
|
||||
Integer findNextPostsNo(Integer boardNo);
|
||||
|
||||
/**
|
||||
* 게시물 조회 수 증가
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @return Long 처리 건수
|
||||
*/
|
||||
Long updateReadCount(Integer boardNo, Integer postsNo);
|
||||
|
||||
/**
|
||||
* 게시물 삭제 여부 수정
|
||||
*
|
||||
* @param posts 게시물 정보(게시판번호, 게시물번호배열)
|
||||
* @param deleteAt 삭제 여부
|
||||
* @param userId 사용자 id
|
||||
* @return Long 처리 건수
|
||||
*/
|
||||
Long updateDeleteAt(Map<Integer, List<Integer>> posts, Integer deleteAt, String userId);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,406 @@
|
||||
package org.egovframe.cloud.boardservice.domain.posts;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.egovframe.cloud.boardservice.api.board.dto.QBoardResponseDto;
|
||||
import org.egovframe.cloud.boardservice.api.posts.dto.PostsListResponseDto;
|
||||
import org.egovframe.cloud.boardservice.api.posts.dto.PostsResponseDto;
|
||||
import org.egovframe.cloud.boardservice.api.posts.dto.PostsSimpleResponseDto;
|
||||
import org.egovframe.cloud.boardservice.api.posts.dto.QPostsListResponseDto;
|
||||
import org.egovframe.cloud.boardservice.api.posts.dto.QPostsResponseDto;
|
||||
import org.egovframe.cloud.boardservice.api.posts.dto.QPostsSimpleResponseDto;
|
||||
import org.egovframe.cloud.boardservice.domain.board.QBoard;
|
||||
import org.egovframe.cloud.boardservice.domain.comment.QComment;
|
||||
import org.egovframe.cloud.boardservice.domain.user.QUser;
|
||||
import org.egovframe.cloud.common.dto.RequestDto;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
||||
import com.google.common.base.CaseFormat;
|
||||
import com.querydsl.core.QueryResults;
|
||||
import com.querydsl.core.Tuple;
|
||||
import com.querydsl.core.types.ExpressionUtils;
|
||||
import com.querydsl.core.types.Order;
|
||||
import com.querydsl.core.types.OrderSpecifier;
|
||||
import com.querydsl.core.types.Path;
|
||||
import com.querydsl.core.types.dsl.BooleanExpression;
|
||||
import com.querydsl.core.types.dsl.CaseBuilder;
|
||||
import com.querydsl.core.types.dsl.Expressions;
|
||||
import com.querydsl.core.types.dsl.NumberPath;
|
||||
import com.querydsl.core.types.dsl.SimpleExpression;
|
||||
import com.querydsl.core.types.dsl.StringPath;
|
||||
import com.querydsl.jpa.JPAExpressions;
|
||||
import com.querydsl.jpa.JPQLQuery;
|
||||
import com.querydsl.jpa.impl.JPAQueryFactory;
|
||||
import com.querydsl.sql.SQLExpressions;
|
||||
import com.querydsl.sql.SQLQuery;
|
||||
import com.querydsl.sql.SQLQueryFactory;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.boardservice.domain.posts.PostsRepositoryImpl
|
||||
* <p>
|
||||
* 게시물 Querydsl 구현 클래스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/07/28
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/07/28 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
public class PostsRepositoryImpl implements PostsRepositoryCustom {
|
||||
|
||||
/**
|
||||
* DML 생성을위한 Querydsl 팩토리 클래스
|
||||
*/
|
||||
private final JPAQueryFactory jpaQueryFactory;
|
||||
|
||||
/**
|
||||
* 쿼리 및 DML 절 생성을 위한 팩토리 클래스
|
||||
*/
|
||||
private final SQLQueryFactory sqlQueryFactory;
|
||||
|
||||
/**
|
||||
* 게시물 페이지 목록 조회
|
||||
* 가급적 Entity 보다는 Dto를 리턴 - Entity 조회시 hibernate 캐시, 불필요 컬럼 조회, oneToOne N+1 문제 발생
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param deleteAt 삭제 여부
|
||||
* @param requestDto 요청 DTO
|
||||
* @param pageable 페이지 정보
|
||||
* @return Page<PostsListResponseDto> 페이지 게시물 목록 응답 DTO
|
||||
*/
|
||||
@Override
|
||||
public Page<PostsListResponseDto> findPage(Integer boardNo, Integer deleteAt, RequestDto requestDto, Pageable pageable) {
|
||||
JPQLQuery<PostsListResponseDto> query = jpaQueryFactory
|
||||
.select(new QPostsListResponseDto(
|
||||
QPosts.posts.postsId.boardNo,
|
||||
QPosts.posts.postsId.postsNo,
|
||||
QPosts.posts.postsTitle,
|
||||
new CaseBuilder()
|
||||
.when(QBoard.board.skinTypeCode.in("faq", "qna"))
|
||||
.then(QPosts.posts.postsContent)
|
||||
.otherwise(""),
|
||||
new CaseBuilder()
|
||||
.when(QBoard.board.skinTypeCode.in("faq", "qna"))
|
||||
.then(QPosts.posts.postsAnswerContent)
|
||||
.otherwise(""),
|
||||
QPosts.posts.readCount,
|
||||
QPosts.posts.noticeAt,
|
||||
QPosts.posts.deleteAt,
|
||||
QPosts.posts.createdBy,
|
||||
QUser.user.userName.as("createdName"),
|
||||
QPosts.posts.createdDate,
|
||||
QBoard.board.newDisplayDayCount,
|
||||
getCommentCountExpression(deleteAt)))
|
||||
.from(QPosts.posts)
|
||||
.innerJoin(QBoard.board).on(QPosts.posts.postsId.boardNo.eq(QBoard.board.boardNo))
|
||||
.fetchJoin()
|
||||
.leftJoin(QUser.user).on(QPosts.posts.createdBy.eq(QUser.user.userId))
|
||||
.fetchJoin()
|
||||
.where(QPosts.posts.postsId.boardNo.eq(boardNo)
|
||||
.and(getBooleanExpression(requestDto.getKeywordType(), requestDto.getKeyword()))
|
||||
.and(getBooleanExpression("deleteAt", deleteAt)));
|
||||
|
||||
//정렬
|
||||
pageable.getSort().stream().forEach(sort -> {
|
||||
Order order = sort.isAscending() ? Order.ASC : Order.DESC;
|
||||
String property = sort.getProperty();
|
||||
Path<?> parent;
|
||||
if ("board_no".equals(property) || "posts_no".equals(property)) parent = QPosts.posts.postsId;
|
||||
else parent = QPosts.posts;
|
||||
|
||||
Path<Object> target = Expressions.path(Object.class, parent, CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, property));
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
OrderSpecifier<?> orderSpecifier = new OrderSpecifier(order, target);
|
||||
query.orderBy(orderSpecifier);
|
||||
});
|
||||
|
||||
QueryResults<PostsListResponseDto> result = query
|
||||
.offset(pageable.getOffset())
|
||||
.limit(pageable.getPageSize()) //페이징
|
||||
.fetchResults();
|
||||
|
||||
return new PageImpl<>(result.getResults(), pageable, result.getTotal());
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시판별 최근 게시물 목록 조회
|
||||
* <p>
|
||||
* JPQL 은 from 절에서 서브쿼리를 사용할 수 없어서 SQLQueryFactory 를 사용해 Native SQL 로 조회
|
||||
* MySQL8 부터는 ROW_NUMBER, RANK 함수를 지원, 탬플릿에서는 MySQL5.7 로 개발해서 mysql 변수를 사용하는 방법으로 조회
|
||||
* MySQL 문법이 포함되어있어서 다른 DBMS 를 사용하는 경우 수정 필요
|
||||
* <p>
|
||||
* 인프런 김영한 강사는 추천하지 않는다.
|
||||
* SqlQueryFactory는 저는 권장하지 않습니다. DB에서 메타데이터를 다 뽑아내서 생성해야 하는데... 너무 복잡하고 기능에 한계도 많습니다.
|
||||
* 따라서 JPA와 JPA용 Querydsl을 최대한 사용하고, 그래도 잘 안되는 부분은 네이티브 쿼리를 사용하는 것이 더 좋다 생각합니다.
|
||||
* <p>
|
||||
* 게시판별로 반복하여 게시물 조회하는 방법 등으로 JPQL 만을 사용해서 조회 가능
|
||||
*
|
||||
* @param boardNos 게시판 번호 목록
|
||||
* @param postsCount 게시물 수
|
||||
* @return List<PostsSimpleResponseDto> 게시물 응답 DTO List
|
||||
*/
|
||||
@Override
|
||||
public List<PostsSimpleResponseDto> findAllByBoardNosLimitCount(List<Integer> boardNos, Integer postsCount) {
|
||||
// path 정의
|
||||
Path<Posts> postsPath = Expressions.path(Posts.class, "posts");
|
||||
NumberPath<Integer> boardNoPath = Expressions.numberPath(Integer.class, postsPath, "board_no");
|
||||
NumberPath<Integer> postsNoPath = Expressions.numberPath(Integer.class, postsPath, "posts_no");
|
||||
|
||||
// 게시판번호, 로우넘 변수
|
||||
StringPath varPath = Expressions.stringPath("v");
|
||||
SQLQuery<Tuple> varSql = SQLExpressions.select(
|
||||
Expressions.stringTemplate("@boardNo := 0"),
|
||||
Expressions.stringTemplate("@rn := 0"));
|
||||
|
||||
// 게시물 조회
|
||||
SQLQuery<Tuple> rownumSql = SQLExpressions
|
||||
.select(boardNoPath,
|
||||
postsNoPath,
|
||||
Expressions.stringPath(postsPath, "posts_title"),
|
||||
Expressions.stringPath(postsPath, "posts_content"),
|
||||
Expressions.datePath(LocalDateTime.class, postsPath, "created_date"),
|
||||
Expressions.stringTemplate("(CASE @boardNo WHEN posts.board_no THEN @rn := @rn + 1 ELSE @rn := 1 END)").as("rn"),
|
||||
Expressions.stringTemplate("(@boardNo := posts.board_no)").as("boardNo"))
|
||||
.from(QPosts.posts, postsPath)
|
||||
.innerJoin(varSql, varPath)
|
||||
.where(boardNoPath.in(boardNos)
|
||||
.and(Expressions.numberPath(Integer.class, postsPath, "delete_at").eq(0)))
|
||||
.orderBy(boardNoPath.asc(), postsNoPath.desc());
|
||||
|
||||
// 최근 게시물 조회
|
||||
return sqlQueryFactory
|
||||
.select(new QPostsSimpleResponseDto(boardNoPath,
|
||||
postsNoPath,
|
||||
Expressions.stringPath(postsPath, "posts_title"),
|
||||
Expressions.stringPath(postsPath, "posts_content"),
|
||||
Expressions.datePath(LocalDateTime.class, postsPath, "created_date")))
|
||||
.from(rownumSql, postsPath)
|
||||
.where(Expressions.numberPath(Integer.class, postsPath, "rn").loe(postsCount))
|
||||
.fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물 상세 조회
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @param userId 사용자 id
|
||||
* @param ipAddr ip 주소
|
||||
* @return PostsResponseDto 게시물 상세 응답 DTO
|
||||
*/
|
||||
@Override
|
||||
public PostsResponseDto findById(Integer boardNo, Integer postsNo, String userId, String ipAddr) {
|
||||
return jpaQueryFactory
|
||||
.select(
|
||||
// 게시물
|
||||
new QPostsResponseDto(
|
||||
QPosts.posts.postsId.boardNo,
|
||||
QPosts.posts.postsId.postsNo,
|
||||
QPosts.posts.postsTitle,
|
||||
QPosts.posts.postsContent,
|
||||
QPosts.posts.postsAnswerContent,
|
||||
QPosts.posts.attachmentCode,
|
||||
QPosts.posts.readCount,
|
||||
QPosts.posts.noticeAt,
|
||||
QPosts.posts.deleteAt,
|
||||
QPosts.posts.createdBy,
|
||||
QUser.user.userName.as("createdName"),
|
||||
QPosts.posts.createdDate,
|
||||
// 게시판
|
||||
new QBoardResponseDto(QBoard.board.boardNo,
|
||||
QBoard.board.boardName,
|
||||
QBoard.board.skinTypeCode,
|
||||
QBoard.board.titleDisplayLength,
|
||||
QBoard.board.postDisplayCount,
|
||||
QBoard.board.pageDisplayCount,
|
||||
QBoard.board.newDisplayDayCount,
|
||||
QBoard.board.editorUseAt,
|
||||
QBoard.board.userWriteAt,
|
||||
QBoard.board.commentUseAt,
|
||||
QBoard.board.uploadUseAt,
|
||||
QBoard.board.uploadLimitCount,
|
||||
QBoard.board.uploadLimitSize),
|
||||
// 댓글 수
|
||||
// getCommentCountExpression(),
|
||||
// 조회 사용자의 게시물 조회 수(조회 수 증가 확인 용)
|
||||
ExpressionUtils.as(
|
||||
JPAExpressions.select(ExpressionUtils.count(QPostsRead.postsRead.userId))
|
||||
.from(QPostsRead.postsRead)
|
||||
.where(QPostsRead.postsRead.postsReadId.boardNo.eq(QPosts.posts.postsId.boardNo)
|
||||
.and(QPostsRead.postsRead.postsReadId.postsNo.eq(QPosts.posts.postsId.postsNo))
|
||||
.and(getBooleanExpression("userId", userId))
|
||||
.and(getBooleanExpression("ipAddr", ipAddr))),
|
||||
"userPostsReadCount")))
|
||||
.from(QPosts.posts) // 게시물
|
||||
.innerJoin(QBoard.board).on(QPosts.posts.postsId.boardNo.eq(QBoard.board.boardNo)) // 게시판
|
||||
.leftJoin(QUser.user).on(QPosts.posts.createdBy.eq(QUser.user.userId)) // 생성자
|
||||
.fetchJoin()
|
||||
.where(QPosts.posts.postsId.boardNo.eq(boardNo)
|
||||
.and(QPosts.posts.postsId.postsNo.eq(postsNo)))
|
||||
.fetchOne();
|
||||
}
|
||||
|
||||
/**
|
||||
* 이전 게시물 조회
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @param gap 차이 -1: 이전, 1: 이후
|
||||
* @param deleteAt 삭제 여부
|
||||
* @param requestDto 요청 DTO
|
||||
* @return List<PostsSimpleResponseDto> 게시물 상세 응답 DTO List
|
||||
*/
|
||||
@Override
|
||||
public List<PostsSimpleResponseDto> findNearPost(Integer boardNo, Integer postsNo, long gap, Integer deleteAt, RequestDto requestDto) {
|
||||
return jpaQueryFactory
|
||||
.select(new QPostsSimpleResponseDto(
|
||||
QPosts.posts.postsId.boardNo,
|
||||
QPosts.posts.postsId.postsNo,
|
||||
QPosts.posts.postsTitle,
|
||||
QPosts.posts.postsContent,
|
||||
QPosts.posts.createdDate))
|
||||
.from(QPosts.posts)
|
||||
.where(QPosts.posts.postsId.boardNo.eq(boardNo)
|
||||
.and(getBooleanExpression(requestDto.getKeywordType(), requestDto.getKeyword()))
|
||||
.and(getBooleanExpression("deleteAt", deleteAt))
|
||||
.and(getBooleanExpression(gap < 0 ? "postsNoLt" : "postsNoGt", postsNo)))
|
||||
.orderBy(gap < 0 ? QPosts.posts.noticeAt.asc() : QPosts.posts.noticeAt.desc(),
|
||||
QPosts.posts.postsId.boardNo.asc(),
|
||||
gap < 0 ? QPosts.posts.postsId.postsNo.desc() : QPosts.posts.postsId.postsNo.asc())
|
||||
.limit((gap < 0 ? -1 : 1) * gap)
|
||||
// .fetchFirst() // 단건 리턴
|
||||
.fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* 다음 게시물 번호 조회
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @return Integer 다음 게시물 번호
|
||||
*/
|
||||
@Override
|
||||
public Integer findNextPostsNo(Integer boardNo) {
|
||||
return jpaQueryFactory
|
||||
.select(QPosts.posts.postsId.postsNo.max().add(1).coalesce(1))
|
||||
.from(QPosts.posts)
|
||||
.where(QPosts.posts.postsId.boardNo.eq(boardNo))
|
||||
.fetchOne();
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물 조회 수 증가
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @return Long 처리 건수
|
||||
*/
|
||||
@Override
|
||||
public Long updateReadCount(Integer boardNo, Integer postsNo) {
|
||||
return jpaQueryFactory.update(QPosts.posts)
|
||||
.set(QPosts.posts.readCount, QPosts.posts.readCount.add(1))
|
||||
.where(QPosts.posts.postsId.boardNo.eq(boardNo)
|
||||
.and(QPosts.posts.postsId.postsNo.eq(postsNo)))
|
||||
.execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물 삭제 여부 수정
|
||||
*
|
||||
* @param posts 게시물 정보(게시판번호, 게시물번호배열)
|
||||
* @param deleteAt 삭제 여부
|
||||
* @param userId 사용자 id
|
||||
* @return Long 수정 건수
|
||||
*/
|
||||
@Override
|
||||
public Long updateDeleteAt(Map<Integer, List<Integer>> posts, Integer deleteAt, String userId) {
|
||||
long updateCount = 0L;
|
||||
|
||||
Iterator<Integer> iterator = posts.keySet().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Integer boardNo = iterator.next();
|
||||
|
||||
List<Integer> postsNoList = posts.get(boardNo);
|
||||
|
||||
updateCount += jpaQueryFactory.update(QPosts.posts)
|
||||
.set(QPosts.posts.deleteAt, deleteAt)
|
||||
.set(QPosts.posts.lastModifiedBy, userId)
|
||||
.set(QPosts.posts.modifiedDate, LocalDateTime.now())
|
||||
.where(QPosts.posts.postsId.boardNo.eq(boardNo)
|
||||
.and(QPosts.posts.postsId.postsNo.in(postsNoList)))
|
||||
.execute();
|
||||
}
|
||||
|
||||
return updateCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* 댓글 수 표현식
|
||||
*
|
||||
* @param deleteAt 삭제 여부
|
||||
* @return SimpleExpression<Long> 댓글 수 표현식
|
||||
*/
|
||||
private SimpleExpression<Long> getCommentCountExpression(Integer deleteAt) {
|
||||
BooleanExpression deleteAtExpression = null;
|
||||
if (deleteAt != null) {
|
||||
deleteAtExpression = deleteAt == 0 ? QComment.comment.deleteAt.eq(0) : QComment.comment.deleteAt.ne(0);
|
||||
}
|
||||
|
||||
return Expressions.as(new CaseBuilder()
|
||||
.when(QBoard.board.commentUseAt.eq(true))
|
||||
.then(JPAExpressions.select(ExpressionUtils.count(QComment.comment.commentId.commentNo))
|
||||
.from(QComment.comment)
|
||||
.where(QComment.comment.commentId.postsId.boardNo.eq(QPosts.posts.postsId.boardNo)
|
||||
.and(QComment.comment.commentId.postsId.postsNo.eq(QPosts.posts.postsId.postsNo))
|
||||
.and(QComment.comment.commentId.postsId.postsNo.eq(QPosts.posts.postsId.postsNo))
|
||||
.and(deleteAtExpression)))
|
||||
.otherwise(0L)
|
||||
, "commentCount");
|
||||
}
|
||||
|
||||
/**
|
||||
* 엔티티 속성별 동적 검색 표현식 리턴
|
||||
*
|
||||
* @param attributeName 속성 명
|
||||
* @param attributeValue 속성 값
|
||||
* @return BooleanExpression 검색 표현식
|
||||
*/
|
||||
private BooleanExpression getBooleanExpression(String attributeName, Object attributeValue) {
|
||||
if (attributeValue == null || "".equals(attributeValue.toString())) return null;
|
||||
|
||||
switch (attributeName) {
|
||||
case "userId": // 사용자 id
|
||||
return QPostsRead.postsRead.userId.eq((String) attributeValue);
|
||||
case "ipAddr": // ip 주소
|
||||
return QPostsRead.postsRead.ipAddr.eq((String) attributeValue);
|
||||
case "deleteAt": // 삭제 여부
|
||||
return QPosts.posts.deleteAt.eq((Integer) attributeValue);
|
||||
case "postsData": // 게시물 제목 + 내용
|
||||
return QPosts.posts.postsTitle.containsIgnoreCase((String) attributeValue).or(QPosts.posts.postsContent.containsIgnoreCase((String) attributeValue));
|
||||
case "postsTitle": // 게시물 제목
|
||||
return QPosts.posts.postsTitle.containsIgnoreCase((String) attributeValue);
|
||||
case "postsContent": // 게시물 내용
|
||||
return QPosts.posts.postsContent.containsIgnoreCase((String) attributeValue);
|
||||
case "postsNoLt": // 게시물 번호
|
||||
return QPosts.posts.postsId.postsNo.lt((Integer) attributeValue);
|
||||
case "postsNoGt": // 게시물 번호
|
||||
return QPosts.posts.postsId.postsNo.gt((Integer) attributeValue);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package org.egovframe.cloud.boardservice.domain.user;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.egovframe.cloud.servlet.domain.BaseEntity;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.boardservice.domain.user.User
|
||||
* <p>
|
||||
* 사용자 정보 엔티티
|
||||
*
|
||||
* @author 표준프레임워크센터 jaeyeolkim
|
||||
* @version 1.0
|
||||
* @since 2021/06/30
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/06/30 jaeyeolkim 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@NoArgsConstructor
|
||||
@Entity
|
||||
@Getter
|
||||
public class User extends BaseEntity implements Serializable {
|
||||
|
||||
/**
|
||||
* serialVersionUID
|
||||
*/
|
||||
private static final long serialVersionUID = 8328774953218952698L;
|
||||
|
||||
@Id
|
||||
@Column(name = "user_no", insertable = false, updatable = false)
|
||||
private Long id;
|
||||
|
||||
@Column(insertable = false, updatable = false)
|
||||
private String userId;
|
||||
|
||||
@Column(insertable = false, updatable = false)
|
||||
private String userName;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
package org.egovframe.cloud.boardservice.service.board;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.egovframe.cloud.boardservice.api.board.dto.BoardListResponseDto;
|
||||
import org.egovframe.cloud.boardservice.api.board.dto.BoardResponseDto;
|
||||
import org.egovframe.cloud.boardservice.api.board.dto.BoardSaveRequestDto;
|
||||
import org.egovframe.cloud.boardservice.api.board.dto.BoardUpdateRequestDto;
|
||||
import org.egovframe.cloud.boardservice.domain.board.Board;
|
||||
import org.egovframe.cloud.boardservice.domain.board.BoardRepository;
|
||||
import org.egovframe.cloud.common.dto.RequestDto;
|
||||
import org.egovframe.cloud.common.exception.EntityNotFoundException;
|
||||
import org.egovframe.cloud.common.service.AbstractService;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.boardservice.service.board.BoardService
|
||||
* <p>
|
||||
* 게시판 서비스 클래스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/07/26
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/07/26 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class BoardService extends AbstractService {
|
||||
|
||||
/**
|
||||
* 게시판 레파지토리 인터페이스
|
||||
*/
|
||||
private final BoardRepository boardRepository;
|
||||
|
||||
/**
|
||||
* 조회 조건에 일치하는 게시판 페이지 목록 조회
|
||||
*
|
||||
* @param requestDto 요청 DTO
|
||||
* @param pageable 페이지 정보
|
||||
* @return Page<BoardListResponseDto> 페이지 게시판 목록 응답 DTO
|
||||
*/
|
||||
public Page<BoardListResponseDto> findPage(RequestDto requestDto, Pageable pageable) {
|
||||
return boardRepository.findPage(requestDto, pageable);
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시판 목록 조회
|
||||
*
|
||||
* @param boardNos 게시판 번호 목록
|
||||
* @return List<BoardResponseDto> 게시판 상세 응답 DTO List
|
||||
*/
|
||||
public List<BoardResponseDto> findAllByBoardNos(List<Integer> boardNos) {
|
||||
return boardRepository.findAllByBoardNoIn(boardNos);
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시판 단건 조회
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @return BoardResponseDto 게시판 응답 DTO
|
||||
*/
|
||||
public BoardResponseDto findById(Integer boardNo) {
|
||||
Board entity = findBoard(boardNo);
|
||||
|
||||
return new BoardResponseDto(entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시판 등록
|
||||
*
|
||||
* @param requestDto 게시판 등록 요청 DTO
|
||||
* @return BoardResponseDto 게시판 응답 DTO
|
||||
*/
|
||||
@Transactional
|
||||
public BoardResponseDto save(BoardSaveRequestDto requestDto) {
|
||||
Board entity = boardRepository.save(requestDto.toEntity());
|
||||
|
||||
return new BoardResponseDto(entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시판 수정
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param requestDto 게시판 수정 요청 DTO
|
||||
* @return BoardResponseDto 게시판 응답 DTO
|
||||
*/
|
||||
@Transactional
|
||||
public BoardResponseDto update(Integer boardNo, BoardUpdateRequestDto requestDto) {
|
||||
Board entity = findBoard(boardNo);
|
||||
|
||||
// 수정
|
||||
entity.update(requestDto.getBoardName(), requestDto.getSkinTypeCode(), requestDto.getTitleDisplayLength(), requestDto.getPostDisplayCount(),
|
||||
requestDto.getPageDisplayCount(), requestDto.getNewDisplayDayCount(), requestDto.getEditorUseAt(), requestDto.getUserWriteAt(),
|
||||
requestDto.getCommentUseAt(), requestDto.getUploadUseAt(), requestDto.getUploadLimitCount(), requestDto.getUploadLimitSize());
|
||||
|
||||
return new BoardResponseDto(entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시판 삭제
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
*/
|
||||
@Transactional
|
||||
public void delete(Integer boardNo) {
|
||||
Board entity = findBoard(boardNo);
|
||||
|
||||
// 삭제
|
||||
boardRepository.delete(entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시판 번호로 게시판 엔티티 조회
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @return Board 게시판 엔티티
|
||||
*/
|
||||
private Board findBoard(Integer boardNo) {
|
||||
return boardRepository.findById(boardNo)
|
||||
.orElseThrow(() -> new EntityNotFoundException(getMessage("valid.notexists.format", new Object[]{getMessage("board")})));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,288 @@
|
||||
package org.egovframe.cloud.boardservice.service.comment;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.egovframe.cloud.boardservice.api.comment.dto.CommentListResponseDto;
|
||||
import org.egovframe.cloud.boardservice.api.comment.dto.CommentResponseDto;
|
||||
import org.egovframe.cloud.boardservice.api.comment.dto.CommentSaveRequestDto;
|
||||
import org.egovframe.cloud.boardservice.api.comment.dto.CommentUpdateRequestDto;
|
||||
import org.egovframe.cloud.boardservice.domain.board.Board;
|
||||
import org.egovframe.cloud.boardservice.domain.comment.Comment;
|
||||
import org.egovframe.cloud.boardservice.domain.comment.CommentId;
|
||||
import org.egovframe.cloud.boardservice.domain.comment.CommentRepository;
|
||||
import org.egovframe.cloud.boardservice.domain.posts.Posts;
|
||||
import org.egovframe.cloud.boardservice.domain.posts.PostsId;
|
||||
import org.egovframe.cloud.boardservice.service.posts.PostsService;
|
||||
import org.egovframe.cloud.common.exception.BusinessMessageException;
|
||||
import org.egovframe.cloud.common.exception.EntityNotFoundException;
|
||||
import org.egovframe.cloud.common.exception.InvalidValueException;
|
||||
import org.egovframe.cloud.common.service.AbstractService;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.boardservice.service.comment.CommentService
|
||||
* <p>
|
||||
* 댓글 서비스 클래스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/08/04
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/08/04 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class CommentService extends AbstractService {
|
||||
|
||||
/**
|
||||
* 게시물 레파지토리 인터페이스
|
||||
*/
|
||||
private final CommentRepository commentRepository;
|
||||
|
||||
/**
|
||||
* 게시물 서비스
|
||||
*/
|
||||
private final PostsService postsService;
|
||||
|
||||
/**
|
||||
* 게시글의 댓글 전체 목록 조회
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @return Map<String, Object> 페이지 댓글 목록 응답 DTO
|
||||
*/
|
||||
public Map<String, Object> findAll(Integer boardNo, Integer postsNo) {
|
||||
return findAll(boardNo, postsNo, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시글의 댓글 전체 목록 조회
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @param deleteAt 삭제 여부
|
||||
* @return Map<String, Object> 페이지 댓글 목록 응답 DTO
|
||||
*/
|
||||
public Map<String, Object> findAll(Integer boardNo, Integer postsNo, Integer deleteAt) {
|
||||
List<CommentListResponseDto> comments = commentRepository.findAll(boardNo, postsNo, deleteAt);
|
||||
|
||||
// 페이지 인터페이스와 동일한 속성의 맵 리턴
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
|
||||
result.put("content", comments);
|
||||
result.put("empty", comments.isEmpty());
|
||||
result.put("first", true);
|
||||
result.put("last", true);
|
||||
result.put("number", 0);
|
||||
result.put("numberOfElements", comments.size());
|
||||
result.put("size", comments.size());
|
||||
result.put("totalElements", comments.size());
|
||||
result.put("totalPages", 1);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시글의 댓글 목록 조회
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @param pageable 페이지 정보
|
||||
* @return Map<String, Object> 페이지 댓글 목록 응답 DTO
|
||||
*/
|
||||
public Map<String, Object> findPage(Integer boardNo, Integer postsNo, Pageable pageable) {
|
||||
return commentRepository.findPage(boardNo, postsNo, null, pageable);
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시글의 댓글 목록 조회
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @param deleteAt 삭제 여부
|
||||
* @param pageable 페이지 정보
|
||||
* @return Map<String, Object> 페이지 댓글 목록 응답 DTO
|
||||
*/
|
||||
public Map<String, Object> findPage(Integer boardNo, Integer postsNo, Integer deleteAt, Pageable pageable) {
|
||||
return commentRepository.findPage(boardNo, postsNo, deleteAt, pageable);
|
||||
}
|
||||
|
||||
/**
|
||||
* 댓글 등록
|
||||
*
|
||||
* @param requestDto 댓글 등록 요청 DTO
|
||||
*/
|
||||
@Transactional
|
||||
public CommentResponseDto save(CommentSaveRequestDto requestDto) {
|
||||
if (requestDto.getBoardNo() == null || requestDto.getPostsNo() == null) {
|
||||
throw new InvalidValueException(getMessage("err.invalid.input.value"));
|
||||
}
|
||||
|
||||
Posts posts = postsService.findPosts(requestDto.getBoardNo(), requestDto.getPostsNo());
|
||||
checkEditableComment(posts); // 저장 가능 여부 확인
|
||||
|
||||
Integer sortSeq;
|
||||
if (requestDto.getParentCommentNo() != null) { // 대댓글
|
||||
sortSeq = commentRepository.findNextSortSeq(requestDto.getBoardNo(), requestDto.getPostsNo(), requestDto.getGroupNo(), requestDto.getParentCommentNo(), requestDto.getDepthSeq());
|
||||
if (sortSeq != null) {
|
||||
commentRepository.updateSortSeq(requestDto.getGroupNo(), sortSeq, null, 1); // 들어갈 위치와 같거나 큰 대댓글 정렬 순서 +1
|
||||
} else {
|
||||
sortSeq = commentRepository.findLastSortSeq(requestDto.getBoardNo(), requestDto.getPostsNo(), requestDto.getGroupNo()); // 들어갈 위치가 검색되지 않으면 max
|
||||
}
|
||||
} else {
|
||||
sortSeq = 1;
|
||||
}
|
||||
|
||||
Integer commentNo = commentRepository.findNextCommentNo(requestDto.getBoardNo(), requestDto.getPostsNo()); // 댓글 번호 채번
|
||||
Integer groupNo; // 댓글 그룹 번호
|
||||
if (requestDto.getGroupNo() != null) groupNo = requestDto.getGroupNo();
|
||||
else groupNo = commentNo; // 최상위 댓글
|
||||
|
||||
Comment entity = commentRepository.save(requestDto.toEntity(posts, commentNo, groupNo, sortSeq));
|
||||
|
||||
return new CommentResponseDto(entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* 댓글 수정(작성자 체크)
|
||||
*
|
||||
* @param requestDto 댓글 수정 요청 DTO
|
||||
*/
|
||||
@Transactional
|
||||
public CommentResponseDto update(CommentUpdateRequestDto requestDto, String userId) {
|
||||
Comment entity = findCommentByCreatedBy(requestDto.getBoardNo(), requestDto.getPostsNo(), requestDto.getCommentNo(), userId);
|
||||
|
||||
checkEditableComment(entity.getPosts()); // 저장 가능 여부 확인
|
||||
|
||||
// 수정
|
||||
entity.update(requestDto.getCommentContent());
|
||||
|
||||
return new CommentResponseDto(entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* 댓글 삭제(작성자 체크)
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @param commentNo 댓글 번호
|
||||
*/
|
||||
@Transactional
|
||||
public void delete(Integer boardNo, Integer postsNo, Integer commentNo, String userId) {
|
||||
Comment entity = findCommentByCreatedBy(boardNo, postsNo, commentNo, userId);
|
||||
|
||||
checkEditableComment(entity.getPosts()); // 변경 가능 여부 확인
|
||||
|
||||
entity.updateDeleteAt(1); // 작성자 삭제
|
||||
}
|
||||
|
||||
/**
|
||||
* 댓글 수정
|
||||
*
|
||||
* @param requestDto 댓글 수정 요청 DTO
|
||||
*/
|
||||
@Transactional
|
||||
public CommentResponseDto update(CommentUpdateRequestDto requestDto) {
|
||||
Comment entity = findComment(requestDto.getBoardNo(), requestDto.getPostsNo(), requestDto.getCommentNo());
|
||||
|
||||
// 수정
|
||||
entity.update(requestDto.getCommentContent());
|
||||
|
||||
return new CommentResponseDto(entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* 댓글 삭제
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @param commentNo 댓글 번호
|
||||
*/
|
||||
@Transactional
|
||||
public void delete(Integer boardNo, Integer postsNo, Integer commentNo) {
|
||||
Comment entity = findComment(boardNo, postsNo, commentNo);
|
||||
|
||||
entity.updateDeleteAt(2); // 관리자 삭제 - 관리자가 본인 댓글 지울 경우 관리자 삭제로 처리
|
||||
}
|
||||
|
||||
/**
|
||||
* 댓글 기본키로 댓글 엔티티 조회
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @param commentNo 댓글 번호
|
||||
* @return Comment 댓글 엔티티
|
||||
*/
|
||||
private Comment findComment(Integer boardNo, Integer postsNo, Integer commentNo) {
|
||||
if (boardNo == null || postsNo == null || commentNo == null) {
|
||||
throw new InvalidValueException(getMessage("err.invalid.input.value"));
|
||||
}
|
||||
|
||||
CommentId id = CommentId.builder()
|
||||
.postsId(PostsId.builder()
|
||||
.boardNo(boardNo)
|
||||
.postsNo(postsNo)
|
||||
.build())
|
||||
.commentNo(commentNo)
|
||||
.build();
|
||||
|
||||
return commentRepository.findById(id)
|
||||
.orElseThrow(() -> new EntityNotFoundException(getMessage("valid.notexists.format", new Object[]{getMessage("comment")}))); // 게시물이(가) 없습니다.
|
||||
}
|
||||
|
||||
/**
|
||||
* 댓글 기본키로 댓글 엔티티 조회
|
||||
* 작성자 체크하여 본인 댓글이 아닌 경우 예외 발생
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @param commentNo 댓글 번호
|
||||
* @param userId 사용자 id
|
||||
* @return Comment 댓글 엔티티
|
||||
*/
|
||||
private Comment findCommentByCreatedBy(Integer boardNo, Integer postsNo, Integer commentNo, String userId) {
|
||||
if (userId == null) {
|
||||
throw new BusinessMessageException(getMessage("err.required.login")); // 로그인 후 다시 시도해주세요.
|
||||
}
|
||||
|
||||
Comment entity = findComment(boardNo, postsNo, commentNo);
|
||||
|
||||
if (!userId.equals(entity.getCreatedBy())) {
|
||||
throw new BusinessMessageException(getMessage("err.unauthorized")); // 권한이 불충분합니다
|
||||
}
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* 댓글 등록/수정/삭제 가능 여부 확인
|
||||
* 댓글 사용 여부, 게시물 삭제 여부 체크해서 예외 발생
|
||||
*
|
||||
* @param posts 게시물 엔티티
|
||||
*/
|
||||
private void checkEditableComment(Posts posts) {
|
||||
Board board = posts.getBoard();
|
||||
if (board == null) {
|
||||
throw new EntityNotFoundException(getMessage("valid.notexists.format", new Object[]{getMessage("board")})); // 게시판이(가) 없습니다.
|
||||
}
|
||||
if (Boolean.FALSE.equals(board.getCommentUseAt())) {
|
||||
throw new BusinessMessageException(getMessage("err.board.not_use_comment")); // 댓글 사용이 금지된 게시판입니다.
|
||||
}
|
||||
if (posts.getDeleteAt().compareTo(0) > 0) {
|
||||
throw new BusinessMessageException(getMessage("err.posts.deleted")); // 삭제된 게시물입니다.
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,411 @@
|
||||
package org.egovframe.cloud.boardservice.service.posts;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.egovframe.cloud.boardservice.api.board.dto.BoardResponseDto;
|
||||
import org.egovframe.cloud.boardservice.api.posts.dto.PostsDeleteRequestDto;
|
||||
import org.egovframe.cloud.boardservice.api.posts.dto.PostsListResponseDto;
|
||||
import org.egovframe.cloud.boardservice.api.posts.dto.PostsResponseDto;
|
||||
import org.egovframe.cloud.boardservice.api.posts.dto.PostsSaveRequestDto;
|
||||
import org.egovframe.cloud.boardservice.api.posts.dto.PostsSimpleResponseDto;
|
||||
import org.egovframe.cloud.boardservice.api.posts.dto.PostsSimpleSaveRequestDto;
|
||||
import org.egovframe.cloud.boardservice.api.posts.dto.PostsUpdateRequestDto;
|
||||
import org.egovframe.cloud.boardservice.domain.posts.Posts;
|
||||
import org.egovframe.cloud.boardservice.domain.posts.PostsId;
|
||||
import org.egovframe.cloud.boardservice.domain.posts.PostsRead;
|
||||
import org.egovframe.cloud.boardservice.domain.posts.PostsReadRepository;
|
||||
import org.egovframe.cloud.boardservice.domain.posts.PostsRepository;
|
||||
import org.egovframe.cloud.boardservice.service.board.BoardService;
|
||||
import org.egovframe.cloud.common.dto.AttachmentEntityMessage;
|
||||
import org.egovframe.cloud.common.dto.RequestDto;
|
||||
import org.egovframe.cloud.common.exception.BusinessMessageException;
|
||||
import org.egovframe.cloud.common.exception.EntityNotFoundException;
|
||||
import org.egovframe.cloud.common.exception.InvalidValueException;
|
||||
import org.egovframe.cloud.common.service.AbstractService;
|
||||
import org.springframework.cloud.stream.function.StreamBridge;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.postsservice.service.posts.PostsService
|
||||
* <p>
|
||||
* 게시물 서비스 클래스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/07/28
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/07/28 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
public class PostsService extends AbstractService {
|
||||
|
||||
/**
|
||||
* 게시물 레파지토리 인터페이스
|
||||
*/
|
||||
private final PostsRepository postsRepository;
|
||||
|
||||
/**
|
||||
* 게시물 조회 레파지토리 인터페이스
|
||||
*/
|
||||
private final PostsReadRepository postsReadRepository;
|
||||
|
||||
/**
|
||||
* 게시판 서비스 클래스
|
||||
*/
|
||||
private final BoardService boardService;
|
||||
|
||||
/**
|
||||
* 이벤트 메시지 발행하기 위한 spring cloud stream 유틸리티 클래스
|
||||
*/
|
||||
private final StreamBridge streamBridge;
|
||||
|
||||
/**
|
||||
* 조회 조건에 일치하는 게시물 페이지 목록 조회
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param deleteAt 삭제 여부
|
||||
* @param requestDto 요청 DTO
|
||||
* @param pageable 페이지 정보
|
||||
* @return Page<PostsListResponseDto> 페이지 게시물 목록 응답 DTO
|
||||
*/
|
||||
public Page<PostsListResponseDto> findPage(Integer boardNo, Integer deleteAt, RequestDto requestDto, Pageable pageable) {
|
||||
if (boardNo == null || boardNo <= 0) throw new InvalidValueException(getMessage("err.invalid.input.value"));
|
||||
return postsRepository.findPage(boardNo, deleteAt, requestDto, pageable);
|
||||
}
|
||||
|
||||
/**
|
||||
* 최근 게시물이 포함된 게시판 목록 조회
|
||||
*
|
||||
* @param boardNos 게시판 번호 목록
|
||||
* @param postsCount 게시물 수
|
||||
* @return Map<Integer, BoardResponseDto> 최근 게시물이 포함된 게시판 상세 응답 DTO Map
|
||||
*/
|
||||
public Map<Integer, BoardResponseDto> findNewest(List<Integer> boardNos, Integer postsCount) {
|
||||
if (boardNos == null || boardNos.isEmpty())
|
||||
throw new InvalidValueException(getMessage("err.invalid.input.value"));
|
||||
|
||||
List<BoardResponseDto> boards = boardService.findAllByBoardNos(boardNos);
|
||||
|
||||
List<PostsSimpleResponseDto> allPosts = postsRepository.findAllByBoardNosLimitCount(boardNos, postsCount);
|
||||
Map<Integer, List<PostsSimpleResponseDto>> postsGroup = allPosts.stream().collect(Collectors.groupingBy(PostsSimpleResponseDto::getBoardNo, Collectors.toList()));
|
||||
|
||||
Map<Integer, BoardResponseDto> data = new HashMap<>(); // 요청한 게시판 순서로 리턴하기 위해서 map 리턴
|
||||
for (BoardResponseDto board : boards) {
|
||||
List<PostsSimpleResponseDto> posts = postsGroup.get(board.getBoardNo())
|
||||
.stream().map(post -> post.setIsNew(board))
|
||||
.collect(Collectors.toList());
|
||||
board.setNewestPosts(posts);
|
||||
data.put(board.getBoardNo(), board);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물 단건 조회
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @param userId 사용자 id
|
||||
* @param ipAddr ip 주소
|
||||
* @return PostsResponseDto 게시물 응답 DTO
|
||||
*/
|
||||
@Transactional
|
||||
public PostsResponseDto findById(Integer boardNo, Integer postsNo, Integer deleteAt, String userId, String ipAddr) {
|
||||
return findById(boardNo, postsNo, deleteAt, userId, ipAddr, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물 단건 조회
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @param deleteAt 삭제 여부
|
||||
* @param userId 사용자 id
|
||||
* @param ipAddr ip 주소
|
||||
* @param requestDto 요청 DTO
|
||||
* @return PostsResponseDto 게시물 응답 DTO
|
||||
*/
|
||||
@Transactional
|
||||
public PostsResponseDto findById(Integer boardNo, Integer postsNo, Integer deleteAt, String userId, String ipAddr, RequestDto requestDto) {
|
||||
PostsResponseDto dto = postsRepository.findById(boardNo, postsNo, userId, ipAddr);
|
||||
|
||||
if (dto == null) {
|
||||
throw new EntityNotFoundException("not found posts : "+ boardNo + ", " + postsNo + ", " + userId + ", " + ipAddr);
|
||||
}
|
||||
|
||||
// 삭제 여부 확인
|
||||
if (deleteAt != null && deleteAt.intValue() != dto.getDeleteAt().intValue()) {
|
||||
throw new BusinessMessageException(getMessage("err.posts.deleted"));
|
||||
}
|
||||
|
||||
if (dto.getUserPostsReadCount() == 0) {
|
||||
// 게시판 조회 등록
|
||||
Integer readNo = postsReadRepository.findNextReadNo(boardNo, postsNo);
|
||||
PostsRead postsRead = PostsRead.builder()
|
||||
.boardNo(boardNo)
|
||||
.postsNo(postsNo)
|
||||
.readNo(readNo)
|
||||
.userId(userId)
|
||||
.ipAddr(ipAddr)
|
||||
.build();
|
||||
|
||||
postsReadRepository.save(postsRead);
|
||||
|
||||
// 조회 수 증가
|
||||
postsRepository.updateReadCount(boardNo, postsNo);
|
||||
|
||||
// dto 조회 수 증가
|
||||
dto.increaseReadCount();
|
||||
}
|
||||
|
||||
// 이전글, 다음글 조회
|
||||
if (requestDto != null) {
|
||||
List<PostsSimpleResponseDto> prevPosts = postsRepository.findNearPost(boardNo, postsNo, -1, deleteAt, requestDto);
|
||||
dto.setPrevPosts(prevPosts);
|
||||
List<PostsSimpleResponseDto> nextPosts = postsRepository.findNearPost(boardNo, postsNo, 1, deleteAt, requestDto);
|
||||
dto.setNextPosts(nextPosts);
|
||||
}
|
||||
|
||||
return dto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물 등록
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param requestDto 게시물 등록 요청 DTO
|
||||
* @return PostsResponseDto 게시물 응답 DTO
|
||||
*/
|
||||
@Transactional
|
||||
public PostsResponseDto save(Integer boardNo, PostsSaveRequestDto requestDto) {
|
||||
Integer postsNo = postsRepository.findNextPostsNo(boardNo);
|
||||
|
||||
Posts entity = postsRepository.save(requestDto.toEntity(boardNo, postsNo));
|
||||
|
||||
/**
|
||||
* 첨부파일 entity 정보 저장 이벤트 발생
|
||||
*/
|
||||
sendAttachmentEvent(entity);
|
||||
|
||||
return new PostsResponseDto(entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물 수정(권한 체크 안함)
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @param requestDto 게시물 수정 요청 DTO
|
||||
* @return PostsResponseDto 게시물 응답 DTO
|
||||
*/
|
||||
@Transactional
|
||||
public PostsResponseDto update(Integer boardNo, Integer postsNo, PostsUpdateRequestDto requestDto) {
|
||||
Posts entity = findPosts(boardNo, postsNo);
|
||||
|
||||
// 수정
|
||||
entity.update(requestDto.getPostsTitle(), requestDto.getPostsContent(), requestDto.getPostsAnswerContent(), requestDto.getAttachmentCode(), requestDto.getNoticeAt());
|
||||
|
||||
return new PostsResponseDto(entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물 다건 삭제(권한 체크 안함)
|
||||
*
|
||||
* @param requestDtoList 게시물 삭제 요청 DTO List
|
||||
* @param userId 사용자 id
|
||||
* @return Long 삭제 건수
|
||||
*/
|
||||
@Transactional
|
||||
public Long remove(List<PostsDeleteRequestDto> requestDtoList, String userId) {
|
||||
Map<Integer, List<Integer>> data = requestDtoList.stream()
|
||||
.collect(Collectors.groupingBy(PostsDeleteRequestDto::getBoardNo,
|
||||
Collectors.mapping(PostsDeleteRequestDto::getPostsNo, Collectors.toList())));
|
||||
|
||||
return postsRepository.updateDeleteAt(data, 2, userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물 다건 복원(권한 체크 안함)
|
||||
*
|
||||
* @param requestDtoList 게시물 삭제 요청 DTO List
|
||||
* @param userId 사용자 id
|
||||
* @return Long 복원 건수
|
||||
*/
|
||||
@Transactional
|
||||
public Long restore(List<PostsDeleteRequestDto> requestDtoList, String userId) {
|
||||
Map<Integer, List<Integer>> data = requestDtoList.stream()
|
||||
.collect(Collectors.groupingBy(PostsDeleteRequestDto::getBoardNo,
|
||||
Collectors.mapping(PostsDeleteRequestDto::getPostsNo, Collectors.toList())));
|
||||
|
||||
return postsRepository.updateDeleteAt(data, 0, userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물 다건 완전 삭제(권한 체크 안함)
|
||||
*
|
||||
* @param requestDtoList 게시물 삭제 요청 DTO List
|
||||
*/
|
||||
@Transactional
|
||||
public void delete(List<PostsDeleteRequestDto> requestDtoList) {
|
||||
List<Posts> deleteEntityList = requestDtoList.stream()
|
||||
.map(PostsDeleteRequestDto::toEntity)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 일괄 처리
|
||||
postsRepository.deleteAll(deleteEntityList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물 등록(작성자 체크)
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param requestDto 게시물 등록 요청 DTO
|
||||
* @return PostsResponseDto 게시물 응답 DTO
|
||||
*/
|
||||
@Transactional
|
||||
public PostsResponseDto save(Integer boardNo, PostsSimpleSaveRequestDto requestDto, String userId) {
|
||||
checkUserWritable(boardNo);
|
||||
|
||||
Integer postsNo = postsRepository.findNextPostsNo(boardNo);
|
||||
|
||||
Posts entity = postsRepository.save(requestDto.toEntity(boardNo, postsNo));
|
||||
|
||||
/**
|
||||
* 첨부파일 entity 정보 저장 이벤트 발생
|
||||
*/
|
||||
sendAttachmentEvent(entity);
|
||||
|
||||
return new PostsResponseDto(entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물 수정(작성자 체크)
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @param requestDto 게시물 수정 요청 DTO
|
||||
* @param userId 사용자 id
|
||||
* @return PostsResponseDto 게시물 응답 DTO
|
||||
*/
|
||||
@Transactional
|
||||
public PostsResponseDto update(Integer boardNo, Integer postsNo, PostsSimpleSaveRequestDto requestDto, String userId) {
|
||||
Posts entity = findPostsByCreatedBy(boardNo, postsNo, userId);
|
||||
|
||||
// 수정
|
||||
entity.update(requestDto.getPostsTitle(), requestDto.getPostsContent(), requestDto.getAttachmentCode());
|
||||
|
||||
return new PostsResponseDto(entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물 삭제(작성자 체크)
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @param userId 사용자 id
|
||||
*/
|
||||
@Transactional
|
||||
public void remove(Integer boardNo, Integer postsNo, String userId) {
|
||||
Posts entity = findPostsByCreatedBy(boardNo, postsNo, userId);
|
||||
|
||||
// 삭제 여부 수정
|
||||
entity.updateDeleteAt(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물 번호로 게시물 엔티티 조회
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @return Posts 게시물 엔티티
|
||||
* @throws InvalidValueException 입력값 예외
|
||||
* @throws EntityNotFoundException 엔티티 예외
|
||||
*/
|
||||
public Posts findPosts(Integer boardNo, Integer postsNo) throws InvalidValueException, EntityNotFoundException {
|
||||
if (boardNo == null || postsNo == null) {
|
||||
throw new InvalidValueException(getMessage("err.invalid.input.value"));
|
||||
}
|
||||
|
||||
PostsId id = PostsId.builder().boardNo(boardNo).postsNo(postsNo).build();
|
||||
|
||||
return postsRepository.findById(id)
|
||||
.orElseThrow(() -> new EntityNotFoundException(getMessage("valid.notexists.format", new Object[]{getMessage("posts")})));
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물 번호, 작성자로 게시물 엔티티 조회
|
||||
* 로그인 확인
|
||||
* 로그인 사용자가 작성자인지 확인
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @param userId 사용자 id
|
||||
* @return Posts 게시물 엔티티
|
||||
* @throws BusinessMessageException 비지니스 예외
|
||||
*/
|
||||
private Posts findPostsByCreatedBy(Integer boardNo, Integer postsNo, String userId) throws BusinessMessageException {
|
||||
if (userId == null || "".equals(userId)) {
|
||||
throw new BusinessMessageException(getMessage("err.required.login")); // 로그인 후 다시 시도해주세요.
|
||||
}
|
||||
|
||||
Posts entity = findPosts(boardNo, postsNo);
|
||||
|
||||
if (!userId.equals(entity.getCreatedBy())) {
|
||||
throw new BusinessMessageException(getMessage("err.unauthorized")); // 권한이 불충분합니다
|
||||
}
|
||||
|
||||
checkUserWritable(boardNo);
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시판 사용자 작성 여부 확인
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @throws BusinessMessageException 비지니스 예외
|
||||
*/
|
||||
private void checkUserWritable(Integer boardNo) throws BusinessMessageException {
|
||||
BoardResponseDto board = boardService.findById(boardNo);
|
||||
if (!Boolean.TRUE.equals(board.getUserWriteAt())) {
|
||||
// 게시판 작성 가능 여부를 알려줄 필요는 없다.
|
||||
throw new BusinessMessageException(getMessage("err.unauthorized")); // 권한이 불충분합니다.
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 첨부파일 entity 정보 업데이트 하기 위해 이벤트 메세지 발행
|
||||
*
|
||||
* @param entity
|
||||
*/
|
||||
private void sendAttachmentEvent(Posts entity) {
|
||||
if (!StringUtils.hasText(entity.getAttachmentCode())) {
|
||||
return;
|
||||
}
|
||||
sendAttachmentEntityInfo(streamBridge,
|
||||
AttachmentEntityMessage.builder()
|
||||
.attachmentCode(entity.getAttachmentCode())
|
||||
.entityName(entity.getClass().getName())
|
||||
.entityId(entity.getPostsId().toString())
|
||||
.build());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package org.egovframe.cloud.boardservice.util;
|
||||
|
||||
import org.egovframe.cloud.common.domain.Role;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.boardservice.util.HttpUtil
|
||||
* <p>
|
||||
* HTTP 관련 유틸 클래스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/09/09
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/09/09 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
public class HttpUtil {
|
||||
|
||||
/**
|
||||
* static method 만으로 구성된 유틸리티 클래스
|
||||
* 객체 생성 금지
|
||||
*/
|
||||
private HttpUtil() {
|
||||
throw new IllegalStateException("Http Utility Class");
|
||||
}
|
||||
|
||||
/***
|
||||
* 관리자 권한 확인
|
||||
* @return boolean 관리자 여부
|
||||
*/
|
||||
public static boolean isAdmin() {
|
||||
return SecurityContextHolder.getContext().getAuthentication().getAuthorities().stream()
|
||||
.anyMatch(r -> r.toString().equals(Role.ADMIN.getKey()));
|
||||
}
|
||||
|
||||
}
|
||||
28
backend/board-service/src/main/resources/application.yml
Normal file
28
backend/board-service/src/main/resources/application.yml
Normal file
@@ -0,0 +1,28 @@
|
||||
server:
|
||||
port: 0 # random port
|
||||
|
||||
spring:
|
||||
application:
|
||||
name: board-service
|
||||
jpa:
|
||||
hibernate:
|
||||
ddl-auto: none
|
||||
properties:
|
||||
hibernate:
|
||||
dialect: org.hibernate.dialect.MySQL57Dialect
|
||||
storage_engine: innodb
|
||||
format_sql: true
|
||||
default_batch_fetch_size: 1000
|
||||
show-sql: true
|
||||
servlet:
|
||||
multipart:
|
||||
enabled: true
|
||||
max-file-size: 10MB
|
||||
max-request-size: 50MB
|
||||
|
||||
# config server actuator
|
||||
management:
|
||||
endpoints:
|
||||
web:
|
||||
exposure:
|
||||
include: refresh, health, beans
|
||||
8
backend/board-service/src/main/resources/bootstrap.yml
Normal file
8
backend/board-service/src/main/resources/bootstrap.yml
Normal file
@@ -0,0 +1,8 @@
|
||||
spring:
|
||||
cloud:
|
||||
config:
|
||||
uri: http://localhost:8888
|
||||
name: board-service # board-service.yml이 있으면 불러오게 된다
|
||||
# name: config-service # config-service의 application.yml 을 불러오게 된다
|
||||
# profiles:
|
||||
# active: prod # application-prod.yml
|
||||
34
backend/board-service/src/main/resources/logback-spring.xml
Normal file
34
backend/board-service/src/main/resources/logback-spring.xml
Normal file
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %thread %-5level %logger - %m%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!-- 로컬에서는 로그를 전송하지 않도록 설정 -->
|
||||
<springProfile name="default">
|
||||
<root level="INFO">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
</springProfile>
|
||||
<springProfile name="!default">
|
||||
<!-- java -Ddestination="localhost:8088" 와 같이 변경할 수 있다. cf 환경에서는 manifest.yml 파일에 환경변수로 추가 -->
|
||||
<property name="destination" value="localhost:8088" />
|
||||
<property name="app_name" value="${app_name}" />
|
||||
|
||||
<!-- ELK - Logstash 로 로그를 전송하기 위한 appender -->
|
||||
<appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
|
||||
<destination>${destination}</destination><!-- native profile => localhost:8088 -->
|
||||
<encoder class="net.logstash.logback.encoder.LogstashEncoder">
|
||||
<customFields>{"app.name":"${app_name}"}</customFields>
|
||||
</encoder>
|
||||
</appender>
|
||||
<root level="WARN">
|
||||
<appender-ref ref="LOGSTASH" />
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
</springProfile>
|
||||
|
||||
</configuration>
|
||||
@@ -0,0 +1,440 @@
|
||||
package org.egovframe.cloud.boardservice.api.board;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.assertj.core.api.Condition;
|
||||
import org.egovframe.cloud.boardservice.api.board.dto.BoardListResponseDto;
|
||||
import org.egovframe.cloud.boardservice.api.board.dto.BoardResponseDto;
|
||||
import org.egovframe.cloud.boardservice.domain.board.Board;
|
||||
import org.egovframe.cloud.boardservice.domain.board.BoardRepository;
|
||||
import org.egovframe.cloud.boardservice.util.RestResponsePage;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.boardservice.api.board.BoardApiControllerTest
|
||||
* <p>
|
||||
* 게시판 Rest API 컨트롤러 테스트 클래스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/07/26
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/07/26 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@Slf4j
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||
@EnableConfigurationProperties
|
||||
@TestPropertySource(properties = {"spring.config.location=classpath:application-test.yml"})
|
||||
@ActiveProfiles(profiles = "test")
|
||||
public class BoardApiControllerTest {
|
||||
|
||||
/**
|
||||
* test rest template
|
||||
*/
|
||||
@Autowired
|
||||
TestRestTemplate restTemplate;
|
||||
|
||||
/**
|
||||
* 게시판 레파지토리 인터페이스
|
||||
*/
|
||||
@Autowired
|
||||
BoardRepository boardRepository;
|
||||
|
||||
/**
|
||||
* 게시판 API 경로
|
||||
*/
|
||||
private static final String URL = "/api/v1/boards";
|
||||
|
||||
/**
|
||||
* 테스트 데이터 등록 횟수
|
||||
*/
|
||||
private final Integer GIVEN_DATA_COUNT = 10;
|
||||
|
||||
/**
|
||||
* 테스트 데이터
|
||||
*/
|
||||
private final String BOARD_NAME_PREFIX = "게시판 명";
|
||||
private final String SKIN_TYPE_CODE_PREFIX = "000";
|
||||
|
||||
private final Integer BOARD_NO = GIVEN_DATA_COUNT + 1;
|
||||
private final String INSERT_BOARD_NAME = BOARD_NAME_PREFIX + "_" + BOARD_NO;
|
||||
private final String INSERT_SKIN_TYPE_CODE = SKIN_TYPE_CODE_PREFIX + "_" + BOARD_NO;
|
||||
private final Integer INSERT_TITLE_DISPLAY_LENGTH = 50;
|
||||
private final Integer INSERT_POST_DISPLAY_COUNT = 10;
|
||||
private final Integer INSERT_PAGE_DISPLAY_COUNT = 10;
|
||||
private final Integer INSERT_NEW_DISPLAY_COUNT = 3;
|
||||
private final Boolean INSERT_EDITOR_USE_AT = true;
|
||||
private final Boolean INSERT_UPLOAD_USE_AT = true;
|
||||
private final Boolean INSERT_USER_WRITE_AT = true;
|
||||
private final Boolean INSERT_COMMENT_USE_AT = true;
|
||||
private final Integer INSERT_UPLOAD_FILE_COUNT = 5;
|
||||
private final BigDecimal INSERT_UPLOAD_LIMIT_SIZE = new BigDecimal("104857600");
|
||||
|
||||
private final String UPDATE_BOARD_NAME = BOARD_NAME_PREFIX + "_" + (BOARD_NO + 1);
|
||||
private final String UPDATE_SKIN_TYPE_CODE = SKIN_TYPE_CODE_PREFIX + "_" + (BOARD_NO + 1);
|
||||
private final Integer UPDATE_TITLE_DISPLAY_LENGTH = 50 + 1;
|
||||
private final Integer UPDATE_POST_DISPLAY_COUNT = 10 + 1;
|
||||
private final Integer UPDATE_PAGE_DISPLAY_COUNT = 10 + 1;
|
||||
private final Integer UPDATE_NEW_DISPLAY_COUNT = 3 + 1;
|
||||
private final Boolean UPDATE_EDITOR_USE_AT = false;
|
||||
private final Boolean UPDATE_UPLOAD_USE_AT = false;
|
||||
private final Boolean UPDATE_USER_WRITE_AT = false;
|
||||
private final Boolean UPDATE_COMMENT_USE_AT = false;
|
||||
private final Integer UPDATE_UPLOAD_FILE_COUNT = 5 + 1;
|
||||
private final BigDecimal UPDATE_UPLOAD_LIMIT_SIZE = new BigDecimal("209715200");
|
||||
|
||||
/**
|
||||
* 테스트 시작 전 수행
|
||||
*/
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
log.info("###setUp");
|
||||
}
|
||||
|
||||
/**
|
||||
* 테스트 종료 후 수행
|
||||
*/
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
log.info("###tearDown");
|
||||
|
||||
//게시판 삭제
|
||||
boardRepository.deleteAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시판 페이지 목록 조회 테스트
|
||||
*/
|
||||
@Test
|
||||
void 게시판_페이지_목록_조회() {
|
||||
log.info("###게시판_페이지_목록_조회");
|
||||
|
||||
// given
|
||||
insertBoards();
|
||||
|
||||
String queryString = "?keywordType=boardName&keyword=" + BOARD_NAME_PREFIX; // 검색 조건
|
||||
queryString += "&page=0&size=" + GIVEN_DATA_COUNT; // 페이지 정보
|
||||
|
||||
// when
|
||||
ResponseEntity<RestResponsePage<BoardListResponseDto>> responseEntity = restTemplate.exchange(
|
||||
URL + queryString,
|
||||
HttpMethod.GET,
|
||||
null,
|
||||
new ParameterizedTypeReference<RestResponsePage<BoardListResponseDto>>() {
|
||||
}
|
||||
);
|
||||
|
||||
// then
|
||||
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
|
||||
RestResponsePage<BoardListResponseDto> page = responseEntity.getBody();
|
||||
assertThat(page).isNotNull();
|
||||
assertThat(page.getNumberOfElements()).isEqualTo(GIVEN_DATA_COUNT);
|
||||
assertThat(page.getContent())
|
||||
.isNotEmpty()
|
||||
.has(new Condition<>(l -> (BOARD_NAME_PREFIX + "_10").equals(l.get(0).getBoardName()), "BoardApiControllerTest.findPage contains " + BOARD_NAME_PREFIX + "_10"))
|
||||
.has(new Condition<>(l -> (BOARD_NAME_PREFIX + "_9").equals(l.get(1).getBoardName()), "BoardApiControllerTest.findPage contains " + BOARD_NAME_PREFIX + "_9"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시판 상세 조회 테스트
|
||||
*/
|
||||
@Test
|
||||
void 게시판_상세_조회() {
|
||||
log.info("###게시판_상세_조회");
|
||||
|
||||
// given
|
||||
Board entity = insertBoard();
|
||||
|
||||
final Integer boardNo = entity.getBoardNo();
|
||||
|
||||
String url = URL + "/" + boardNo;
|
||||
|
||||
// when
|
||||
ResponseEntity<BoardResponseDto> responseEntity = restTemplate.exchange(
|
||||
url,
|
||||
HttpMethod.GET,
|
||||
null,
|
||||
new ParameterizedTypeReference<BoardResponseDto>() {
|
||||
}
|
||||
);
|
||||
|
||||
// then
|
||||
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
|
||||
BoardResponseDto dto = responseEntity.getBody();
|
||||
assertThat(dto).isNotNull();
|
||||
assertThat(dto.getBoardNo()).isEqualTo(boardNo);
|
||||
assertThat(dto.getBoardName()).isEqualTo(INSERT_BOARD_NAME);
|
||||
assertThat(dto.getSkinTypeCode()).isEqualTo(INSERT_SKIN_TYPE_CODE);
|
||||
assertThat(dto.getTitleDisplayLength()).isEqualTo(INSERT_TITLE_DISPLAY_LENGTH);
|
||||
assertThat(dto.getPostDisplayCount()).isEqualTo(INSERT_POST_DISPLAY_COUNT);
|
||||
assertThat(dto.getPageDisplayCount()).isEqualTo(INSERT_PAGE_DISPLAY_COUNT);
|
||||
assertThat(dto.getNewDisplayDayCount()).isEqualTo(INSERT_NEW_DISPLAY_COUNT);
|
||||
assertThat(dto.getEditorUseAt()).isEqualTo(INSERT_EDITOR_USE_AT);
|
||||
assertThat(dto.getUploadUseAt()).isEqualTo(INSERT_UPLOAD_USE_AT);
|
||||
assertThat(dto.getUserWriteAt()).isEqualTo(INSERT_USER_WRITE_AT);
|
||||
assertThat(dto.getCommentUseAt()).isEqualTo(INSERT_COMMENT_USE_AT);
|
||||
assertThat(dto.getUploadLimitCount()).isEqualTo(INSERT_UPLOAD_FILE_COUNT);
|
||||
assertThat(dto.getUploadLimitSize()).isEqualTo(INSERT_UPLOAD_LIMIT_SIZE);
|
||||
|
||||
deleteBoard(boardNo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시판 등록 테스트
|
||||
*/
|
||||
@Test
|
||||
void 게시판_등록() {
|
||||
log.info("###게시판_등록");
|
||||
|
||||
// given
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("boardName", INSERT_BOARD_NAME);
|
||||
params.put("skinTypeCode", INSERT_SKIN_TYPE_CODE);
|
||||
params.put("titleDisplayLength", INSERT_TITLE_DISPLAY_LENGTH);
|
||||
params.put("postDisplayCount", INSERT_POST_DISPLAY_COUNT);
|
||||
params.put("pageDisplayCount", INSERT_PAGE_DISPLAY_COUNT);
|
||||
params.put("newDisplayDayCount", INSERT_NEW_DISPLAY_COUNT);
|
||||
params.put("editorUseAt", INSERT_EDITOR_USE_AT);
|
||||
params.put("uploadUseAt", INSERT_UPLOAD_USE_AT);
|
||||
params.put("userWriteAt", INSERT_USER_WRITE_AT);
|
||||
params.put("commentUseAt", INSERT_COMMENT_USE_AT);
|
||||
params.put("uploadLimitCount", INSERT_UPLOAD_FILE_COUNT);
|
||||
params.put("uploadLimitSize", INSERT_UPLOAD_LIMIT_SIZE);
|
||||
HttpEntity<Map<String, Object>> httpEntity = new HttpEntity<>(params);
|
||||
|
||||
// when
|
||||
//ResponseEntity<PostsResponseDto> responseEntity = restTemplate.postForEntity(URL, requestDto, PostsResponseDto.class);
|
||||
ResponseEntity<BoardResponseDto> responseEntity = restTemplate.exchange(
|
||||
URL,
|
||||
HttpMethod.POST,
|
||||
httpEntity,
|
||||
new ParameterizedTypeReference<BoardResponseDto>() {
|
||||
}
|
||||
);
|
||||
|
||||
// then
|
||||
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
|
||||
BoardResponseDto dto = responseEntity.getBody();
|
||||
assertThat(dto).isNotNull();
|
||||
|
||||
final Integer boardNo = dto.getBoardNo();
|
||||
|
||||
Optional<Board> board = selectData(boardNo);
|
||||
assertThat(board).isPresent();
|
||||
|
||||
Board entity = board.get();
|
||||
assertThat(entity.getBoardNo()).isEqualTo(boardNo);
|
||||
assertThat(entity.getBoardName()).isEqualTo(INSERT_BOARD_NAME);
|
||||
assertThat(entity.getSkinTypeCode()).isEqualTo(INSERT_SKIN_TYPE_CODE);
|
||||
assertThat(entity.getTitleDisplayLength()).isEqualTo(INSERT_TITLE_DISPLAY_LENGTH);
|
||||
assertThat(entity.getPostDisplayCount()).isEqualTo(INSERT_POST_DISPLAY_COUNT);
|
||||
assertThat(entity.getPageDisplayCount()).isEqualTo(INSERT_PAGE_DISPLAY_COUNT);
|
||||
assertThat(entity.getNewDisplayDayCount()).isEqualTo(INSERT_NEW_DISPLAY_COUNT);
|
||||
assertThat(entity.getEditorUseAt()).isEqualTo(INSERT_EDITOR_USE_AT);
|
||||
assertThat(entity.getUploadUseAt()).isEqualTo(INSERT_UPLOAD_USE_AT);
|
||||
assertThat(entity.getUserWriteAt()).isEqualTo(INSERT_USER_WRITE_AT);
|
||||
assertThat(entity.getCommentUseAt()).isEqualTo(INSERT_COMMENT_USE_AT);
|
||||
assertThat(entity.getUploadLimitCount()).isEqualTo(INSERT_UPLOAD_FILE_COUNT);
|
||||
assertThat(entity.getUploadLimitSize()).isEqualTo(INSERT_UPLOAD_LIMIT_SIZE);
|
||||
|
||||
deleteBoard(boardNo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시판 수정 테스트
|
||||
*/
|
||||
@Test
|
||||
void 게시판_수정() {
|
||||
log.info("###게시판_수정");
|
||||
|
||||
// given
|
||||
Board entity = insertBoard();
|
||||
|
||||
final Integer boardNo = entity.getBoardNo();
|
||||
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("boardName", UPDATE_BOARD_NAME);
|
||||
params.put("skinTypeCode", UPDATE_SKIN_TYPE_CODE);
|
||||
params.put("titleDisplayLength", UPDATE_TITLE_DISPLAY_LENGTH);
|
||||
params.put("postDisplayCount", UPDATE_POST_DISPLAY_COUNT);
|
||||
params.put("pageDisplayCount", UPDATE_PAGE_DISPLAY_COUNT);
|
||||
params.put("newDisplayDayCount", UPDATE_NEW_DISPLAY_COUNT);
|
||||
params.put("editorUseAt", UPDATE_EDITOR_USE_AT);
|
||||
params.put("uploadUseAt", UPDATE_UPLOAD_USE_AT);
|
||||
params.put("userWriteAt", UPDATE_USER_WRITE_AT);
|
||||
params.put("commentUseAt", UPDATE_COMMENT_USE_AT);
|
||||
params.put("uploadLimitCount", UPDATE_UPLOAD_FILE_COUNT);
|
||||
params.put("uploadLimitSize", UPDATE_UPLOAD_LIMIT_SIZE);
|
||||
HttpEntity<Map<String, Object>> httpEntity = new HttpEntity<>(params);
|
||||
|
||||
String url = URL + "/" + boardNo;
|
||||
|
||||
// when
|
||||
ResponseEntity<BoardResponseDto> responseEntity = restTemplate.exchange(
|
||||
url,
|
||||
HttpMethod.PUT,
|
||||
httpEntity,
|
||||
new ParameterizedTypeReference<BoardResponseDto>() {
|
||||
}
|
||||
);
|
||||
|
||||
// then
|
||||
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
|
||||
BoardResponseDto dto = responseEntity.getBody();
|
||||
assertThat(dto).isNotNull();
|
||||
|
||||
Optional<Board> board = selectData(boardNo);
|
||||
assertThat(board).isPresent();
|
||||
|
||||
Board updatedBoard = board.get();
|
||||
assertThat(updatedBoard.getBoardNo()).isEqualTo(boardNo);
|
||||
assertThat(updatedBoard.getBoardName()).isEqualTo(UPDATE_BOARD_NAME);
|
||||
assertThat(updatedBoard.getSkinTypeCode()).isEqualTo(UPDATE_SKIN_TYPE_CODE);
|
||||
assertThat(updatedBoard.getTitleDisplayLength()).isEqualTo(UPDATE_TITLE_DISPLAY_LENGTH);
|
||||
assertThat(updatedBoard.getPostDisplayCount()).isEqualTo(UPDATE_POST_DISPLAY_COUNT);
|
||||
assertThat(updatedBoard.getPageDisplayCount()).isEqualTo(UPDATE_PAGE_DISPLAY_COUNT);
|
||||
assertThat(updatedBoard.getNewDisplayDayCount()).isEqualTo(UPDATE_NEW_DISPLAY_COUNT);
|
||||
assertThat(updatedBoard.getEditorUseAt()).isEqualTo(UPDATE_EDITOR_USE_AT);
|
||||
assertThat(updatedBoard.getUploadUseAt()).isEqualTo(UPDATE_UPLOAD_USE_AT);
|
||||
assertThat(updatedBoard.getUserWriteAt()).isEqualTo(UPDATE_USER_WRITE_AT);
|
||||
assertThat(updatedBoard.getCommentUseAt()).isEqualTo(UPDATE_COMMENT_USE_AT);
|
||||
assertThat(updatedBoard.getUploadLimitCount()).isEqualTo(UPDATE_UPLOAD_FILE_COUNT);
|
||||
assertThat(updatedBoard.getUploadLimitSize()).isEqualTo(UPDATE_UPLOAD_LIMIT_SIZE);
|
||||
|
||||
deleteBoard(boardNo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시판 삭제 테스트
|
||||
*/
|
||||
@Test
|
||||
void 게시판_삭제() {
|
||||
log.info("###게시판_삭제");
|
||||
|
||||
// given
|
||||
Board entity = insertBoard();
|
||||
|
||||
final Integer boardNo = entity.getBoardNo();
|
||||
|
||||
String url = URL + "/" + boardNo;
|
||||
|
||||
// when
|
||||
ResponseEntity<BoardResponseDto> responseEntity = restTemplate.exchange(
|
||||
url,
|
||||
HttpMethod.DELETE,
|
||||
null,
|
||||
BoardResponseDto.class
|
||||
);
|
||||
|
||||
// then
|
||||
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
|
||||
Optional<Board> board = selectData(boardNo);
|
||||
assertThat(board).isNotPresent();
|
||||
}
|
||||
|
||||
/**
|
||||
* 테스트 데이터 등록
|
||||
*/
|
||||
private void insertBoards() {
|
||||
log.info("###테스트 데이터 등록");
|
||||
|
||||
List<Board> list = new ArrayList<>();
|
||||
for (int i = 1; i <= GIVEN_DATA_COUNT; i++) {
|
||||
list.add(Board.builder()
|
||||
.boardName(BOARD_NAME_PREFIX + "_" + i)
|
||||
.skinTypeCode(SKIN_TYPE_CODE_PREFIX + "_" + i)
|
||||
.titleDisplayLength(INSERT_TITLE_DISPLAY_LENGTH + i)
|
||||
.postDisplayCount(INSERT_POST_DISPLAY_COUNT + i)
|
||||
.pageDisplayCount(INSERT_PAGE_DISPLAY_COUNT + i)
|
||||
.newDisplayDayCount(INSERT_NEW_DISPLAY_COUNT + i)
|
||||
.editorUseAt(i % 2 == 1)
|
||||
.uploadUseAt(i % 3 == 0)
|
||||
.userWriteAt(i % 3 == 0)
|
||||
.commentUseAt(i % 2 == 0)
|
||||
.uploadLimitCount(INSERT_UPLOAD_FILE_COUNT + i)
|
||||
.uploadLimitSize(INSERT_UPLOAD_LIMIT_SIZE.add(new BigDecimal(String.valueOf(i))))
|
||||
.build());
|
||||
}
|
||||
|
||||
boardRepository.saveAll(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 테스트 데이터 단건 등록
|
||||
*
|
||||
* @return Board 게시판 엔티티
|
||||
*/
|
||||
private Board insertBoard() {
|
||||
log.info("###테스트 데이터 단건 등록");
|
||||
|
||||
return boardRepository.save(Board.builder()
|
||||
.boardName(INSERT_BOARD_NAME)
|
||||
.skinTypeCode(INSERT_SKIN_TYPE_CODE)
|
||||
.titleDisplayLength(INSERT_TITLE_DISPLAY_LENGTH)
|
||||
.postDisplayCount(INSERT_POST_DISPLAY_COUNT)
|
||||
.pageDisplayCount(INSERT_PAGE_DISPLAY_COUNT)
|
||||
.newDisplayDayCount(INSERT_NEW_DISPLAY_COUNT)
|
||||
.editorUseAt(INSERT_EDITOR_USE_AT)
|
||||
.uploadUseAt(INSERT_UPLOAD_USE_AT)
|
||||
.userWriteAt(INSERT_USER_WRITE_AT)
|
||||
.commentUseAt(INSERT_COMMENT_USE_AT)
|
||||
.uploadLimitCount(INSERT_UPLOAD_FILE_COUNT)
|
||||
.uploadLimitSize(INSERT_UPLOAD_LIMIT_SIZE)
|
||||
.build());
|
||||
}
|
||||
|
||||
/**
|
||||
* 테스트 데이터 단건 삭제
|
||||
*/
|
||||
private void deleteBoard(Integer boardNo) {
|
||||
log.info("###테스트 데이터 단건 삭제");
|
||||
|
||||
boardRepository.deleteById(boardNo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 테스트 데이터 단건 조회
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @return Optional<Board> 게시판 엔티티
|
||||
*/
|
||||
private Optional<Board> selectData(Integer boardNo) {
|
||||
log.info("###테스트 데이터 단건 조회");
|
||||
|
||||
return boardRepository.findById(boardNo);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,585 @@
|
||||
package org.egovframe.cloud.boardservice.api.comment;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.egovframe.cloud.boardservice.api.board.dto.BoardResponseDto;
|
||||
import org.egovframe.cloud.boardservice.api.comment.dto.CommentResponseDto;
|
||||
import org.egovframe.cloud.boardservice.domain.board.Board;
|
||||
import org.egovframe.cloud.boardservice.domain.board.BoardRepository;
|
||||
import org.egovframe.cloud.boardservice.domain.comment.Comment;
|
||||
import org.egovframe.cloud.boardservice.domain.comment.CommentId;
|
||||
import org.egovframe.cloud.boardservice.domain.comment.CommentRepository;
|
||||
import org.egovframe.cloud.boardservice.domain.posts.Posts;
|
||||
import org.egovframe.cloud.boardservice.domain.posts.PostsId;
|
||||
import org.egovframe.cloud.boardservice.domain.posts.PostsRepository;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.boardservice.api.posts.CommentApiControllerTest
|
||||
* <p>
|
||||
* 댓글 Rest API 컨트롤러 클래스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/08/11
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/08/11 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@Slf4j
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||
@EnableConfigurationProperties
|
||||
@TestPropertySource(properties = {"spring.config.location=classpath:application-test.yml"})
|
||||
@ActiveProfiles(profiles = "test")
|
||||
class CommentApiControllerTest {
|
||||
|
||||
/**
|
||||
* test rest template
|
||||
*/
|
||||
@Autowired
|
||||
TestRestTemplate restTemplate;
|
||||
|
||||
/**
|
||||
* 게시판 레파지토리 인터페이스
|
||||
*/
|
||||
@Autowired
|
||||
BoardRepository boardRepository;
|
||||
|
||||
/**
|
||||
* 게시물 레파지토리 인터페이스
|
||||
*/
|
||||
@Autowired
|
||||
PostsRepository postsRepository;
|
||||
|
||||
/**
|
||||
* 댓글 레파지토리 인터페이스
|
||||
*/
|
||||
@Autowired
|
||||
CommentRepository commentRepository;
|
||||
|
||||
/**
|
||||
* 게시판 API 경로
|
||||
*/
|
||||
private static final String URL = "/api/v1/comments";
|
||||
|
||||
/**
|
||||
* 테스트 데이터 등록 횟수
|
||||
*/
|
||||
private final Integer GIVEN_DATA_COUNT = 10;
|
||||
|
||||
/**
|
||||
* 테스트 데이터
|
||||
*/
|
||||
private Board board;
|
||||
private Posts posts;
|
||||
|
||||
private final Integer INSERT_COMMENT_NO = 1;
|
||||
private final String INSERT_COMMENT_CONTENT = "댓글 내용";
|
||||
|
||||
private final String UPDATE_COMMENT_CONTENT = "댓글 내용 수정";
|
||||
|
||||
/**
|
||||
* 테스트 시작 전 수행
|
||||
*/
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
log.info("###setUp");
|
||||
|
||||
// 게시판 등록
|
||||
board = boardRepository.save(Board.builder()
|
||||
.boardName("일반게시판1")
|
||||
.skinTypeCode("normal")
|
||||
.titleDisplayLength(50)
|
||||
.postDisplayCount(50)
|
||||
.pageDisplayCount(50)
|
||||
.newDisplayDayCount(50)
|
||||
.editorUseAt(true)
|
||||
.uploadUseAt(true)
|
||||
.uploadLimitCount(50)
|
||||
.uploadLimitSize(new BigDecimal("52428800"))
|
||||
.userWriteAt(true)
|
||||
.commentUseAt(true)
|
||||
.build());
|
||||
|
||||
// 게시물 등록
|
||||
posts = postsRepository.save(Posts.builder()
|
||||
.board(board)
|
||||
.postsId(PostsId.builder()
|
||||
.boardNo(board.getBoardNo())
|
||||
.postsNo(1)
|
||||
.build())
|
||||
.postsTitle("게시물 1")
|
||||
.postsContent("게시물 내용 1")
|
||||
.postsAnswerContent("게시물 답변 내용 1")
|
||||
.attachmentCode("0000000001")
|
||||
.readCount(0)
|
||||
.noticeAt(false)
|
||||
.deleteAt(0)
|
||||
.build());
|
||||
}
|
||||
|
||||
/**
|
||||
* 테스트 종료 후 수행
|
||||
*/
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
log.info("###tearDown");
|
||||
|
||||
// 댓글 삭제
|
||||
commentRepository.deleteAll();
|
||||
|
||||
// 게시물 삭제
|
||||
postsRepository.deleteAll();
|
||||
|
||||
// 게시판 삭제
|
||||
boardRepository.deleteAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시글의 전체 댓글 목록 조회
|
||||
*/
|
||||
@Test
|
||||
void 게시글의_전체_댓글_목록_조회() {
|
||||
log.info("###게시글의_전체_댓글_목록_조회");
|
||||
|
||||
// given
|
||||
insertComments();
|
||||
|
||||
final String url = URL + "/total/" + posts.getPostsId().getBoardNo() + "/" + posts.getPostsId().getPostsNo();
|
||||
|
||||
// when
|
||||
ResponseEntity<Map<String, Object>> responseEntity = restTemplate.exchange(
|
||||
url,
|
||||
HttpMethod.GET,
|
||||
null,
|
||||
new ParameterizedTypeReference<Map<String, Object>>() {
|
||||
}
|
||||
);
|
||||
|
||||
// then
|
||||
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
|
||||
Map<String, Object> data = responseEntity.getBody();
|
||||
|
||||
assertThat(data).isNotNull();
|
||||
assertThat(data.get("numberOfElements")).isEqualTo(GIVEN_DATA_COUNT);
|
||||
assertThat(data.get("totalElements")).isEqualTo(GIVEN_DATA_COUNT);
|
||||
assertThat(data.get("totalPages")).isEqualTo(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시글의 전체 미삭제 댓글 목록 조회
|
||||
*/
|
||||
@Test
|
||||
void 게시글의_전체_미삭제_댓글_목록_조회() {
|
||||
log.info("###게시글의_전체_미삭제_댓글_목록_조회");
|
||||
|
||||
// given
|
||||
insertComments();
|
||||
|
||||
final String url = URL + "/all/" + posts.getPostsId().getBoardNo() + "/" + posts.getPostsId().getPostsNo();
|
||||
|
||||
// when
|
||||
ResponseEntity<Map<String, Object>> responseEntity = restTemplate.exchange(
|
||||
url,
|
||||
HttpMethod.GET,
|
||||
null,
|
||||
new ParameterizedTypeReference<Map<String, Object>>() {
|
||||
}
|
||||
);
|
||||
|
||||
// then
|
||||
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
|
||||
Map<String, Object> data = responseEntity.getBody();
|
||||
|
||||
assertThat(data).isNotNull();
|
||||
assertThat(data.get("numberOfElements")).isEqualTo(GIVEN_DATA_COUNT / 3);
|
||||
assertThat(data.get("totalElements")).isEqualTo(GIVEN_DATA_COUNT / 3);
|
||||
assertThat(data.get("totalPages")).isEqualTo(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시글의 댓글 목록 조회
|
||||
*/
|
||||
@Test
|
||||
void 게시글의_댓글_목록_조회() {
|
||||
log.info("###게시글의_댓글_목록_조회");
|
||||
|
||||
// given
|
||||
insertComments();
|
||||
|
||||
final Integer page = 0;
|
||||
final Integer size = 5;
|
||||
final String url = URL + "/" + posts.getPostsId().getBoardNo() + "/" + posts.getPostsId().getPostsNo() + "?page=" + page + "&size=" + size;
|
||||
|
||||
// when
|
||||
ResponseEntity<Map<String, Object>> responseEntity = restTemplate.exchange(
|
||||
url,
|
||||
HttpMethod.GET,
|
||||
null,
|
||||
new ParameterizedTypeReference<Map<String, Object>>() {
|
||||
}
|
||||
);
|
||||
|
||||
// then
|
||||
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
|
||||
Map<String, Object> data = responseEntity.getBody();
|
||||
|
||||
assertThat(data).isNotNull();
|
||||
assertThat(data.get("numberOfElements")).isEqualTo(size);
|
||||
assertThat(data.get("totalElements")).isEqualTo(GIVEN_DATA_COUNT);
|
||||
assertThat(data.get("totalPages")).isEqualTo(GIVEN_DATA_COUNT / size);
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시글의 미삭제 댓글 목록 조회
|
||||
*/
|
||||
@Test
|
||||
void 게시글의_미삭제_댓글_목록_조회() {
|
||||
log.info("###게시글의_미삭제_댓글_목록_조회");
|
||||
|
||||
// given
|
||||
insertComments();
|
||||
|
||||
final Integer page = 0;
|
||||
final Integer size = 5;
|
||||
final String url = URL + "/list/" + posts.getPostsId().getBoardNo() + "/" + posts.getPostsId().getPostsNo() + "?page=" + page + "&size=" + size;
|
||||
|
||||
// when
|
||||
ResponseEntity<Map<String, Object>> responseEntity = restTemplate.exchange(
|
||||
url,
|
||||
HttpMethod.GET,
|
||||
null,
|
||||
new ParameterizedTypeReference<Map<String, Object>>() {
|
||||
}
|
||||
);
|
||||
|
||||
// then
|
||||
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
|
||||
Map<String, Object> data = responseEntity.getBody();
|
||||
|
||||
assertThat(data).isNotNull();
|
||||
assertThat(data.get("numberOfElements")).isEqualTo(GIVEN_DATA_COUNT / 3);
|
||||
assertThat(data.get("totalElements")).isEqualTo(GIVEN_DATA_COUNT / 3);
|
||||
assertThat(data.get("totalPages")).isEqualTo(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 댓글 등록
|
||||
*/
|
||||
@Test
|
||||
void 댓글_등록() {
|
||||
log.info("###댓글_등록");
|
||||
|
||||
// given
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("boardNo", posts.getPostsId().getBoardNo());
|
||||
params.put("postsNo", posts.getPostsId().getPostsNo());
|
||||
params.put("commentContent", INSERT_COMMENT_CONTENT);
|
||||
params.put("depthSeq", 0);
|
||||
params.put("parentCommentNo", null);
|
||||
HttpEntity<Map<String, Object>> httpEntity = new HttpEntity<>(params);
|
||||
|
||||
// when
|
||||
ResponseEntity<CommentResponseDto> responseEntity = restTemplate.exchange(
|
||||
URL,
|
||||
HttpMethod.POST,
|
||||
httpEntity,
|
||||
new ParameterizedTypeReference<CommentResponseDto>() {
|
||||
}
|
||||
);
|
||||
|
||||
// then
|
||||
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
|
||||
CommentResponseDto dto = responseEntity.getBody();
|
||||
assertThat(dto).isNotNull();
|
||||
|
||||
final Integer boardNo = dto.getBoardNo();
|
||||
final Integer postsNo = dto.getPostsNo();
|
||||
final Integer commentNo = dto.getCommentNo();
|
||||
|
||||
Optional<Comment> comment = selectData(boardNo, postsNo, commentNo);
|
||||
assertThat(comment).isPresent();
|
||||
|
||||
Comment entity = comment.get();
|
||||
assertThat(entity.getCommentId().getPostsId().getBoardNo()).isEqualTo(boardNo);
|
||||
assertThat(entity.getCommentId().getPostsId().getPostsNo()).isEqualTo(postsNo);
|
||||
assertThat(entity.getCommentId().getCommentNo()).isEqualTo(commentNo);
|
||||
assertThat(entity.getCommentContent()).isEqualTo(INSERT_COMMENT_CONTENT);
|
||||
assertThat(entity.getParentCommentNo()).isNull();
|
||||
assertThat(entity.getDeleteAt()).isZero();
|
||||
}
|
||||
|
||||
/**
|
||||
* 댓글 수정 작성자체크
|
||||
*/
|
||||
@Test
|
||||
void 댓글_수정_작성자체크() {
|
||||
log.info("###댓글_수정 작성자체크");
|
||||
|
||||
// given
|
||||
Comment entity = insertComment();
|
||||
|
||||
final Integer boardNo = entity.getCommentId().getPostsId().getBoardNo();
|
||||
final Integer postsNo = entity.getCommentId().getPostsId().getPostsNo();
|
||||
final Integer commentNo = entity.getCommentId().getCommentNo();
|
||||
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("boardNo", boardNo);
|
||||
params.put("postsNo", postsNo);
|
||||
params.put("commentNo", commentNo);
|
||||
params.put("commentContent", UPDATE_COMMENT_CONTENT);
|
||||
HttpEntity<Map<String, Object>> httpEntity = new HttpEntity<>(params);
|
||||
|
||||
String url = URL + "/update";
|
||||
|
||||
// when
|
||||
ResponseEntity<CommentResponseDto> responseEntity = restTemplate.exchange(
|
||||
url,
|
||||
HttpMethod.PUT,
|
||||
httpEntity,
|
||||
new ParameterizedTypeReference<CommentResponseDto>() {
|
||||
}
|
||||
);
|
||||
|
||||
// then
|
||||
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST); // 본인글 아닌 경우 예외 발생
|
||||
}
|
||||
|
||||
/**
|
||||
* 댓글 삭제 작성자체크
|
||||
*/
|
||||
@Test
|
||||
void 댓글_삭제_작성자체크() {
|
||||
log.info("###댓글_삭제 작성자체크");
|
||||
|
||||
// given
|
||||
Comment entity = insertComment();
|
||||
|
||||
final Integer boardNo = entity.getCommentId().getPostsId().getBoardNo();
|
||||
final Integer postsNo = entity.getCommentId().getPostsId().getPostsNo();
|
||||
final Integer commentNo = entity.getCommentId().getCommentNo();
|
||||
|
||||
String url = URL + "/delete/" + boardNo + "/" + postsNo + "/" + commentNo;
|
||||
|
||||
// when
|
||||
ResponseEntity<BoardResponseDto> responseEntity = restTemplate.exchange(
|
||||
url,
|
||||
HttpMethod.DELETE,
|
||||
null,
|
||||
BoardResponseDto.class
|
||||
);
|
||||
|
||||
// then
|
||||
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST); // 관리자권한 or 본인글 아닌 경우 예외 발생
|
||||
}
|
||||
|
||||
/**
|
||||
* 댓글 수정
|
||||
*/
|
||||
@Test
|
||||
void 댓글_수정() {
|
||||
log.info("###댓글_수정");
|
||||
|
||||
// given
|
||||
Comment entity = insertComment();
|
||||
|
||||
final Integer boardNo = entity.getCommentId().getPostsId().getBoardNo();
|
||||
final Integer postsNo = entity.getCommentId().getPostsId().getPostsNo();
|
||||
final Integer commentNo = entity.getCommentId().getCommentNo();
|
||||
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("boardNo", boardNo);
|
||||
params.put("postsNo", postsNo);
|
||||
params.put("commentNo", commentNo);
|
||||
params.put("commentContent", UPDATE_COMMENT_CONTENT);
|
||||
HttpEntity<Map<String, Object>> httpEntity = new HttpEntity<>(params);
|
||||
|
||||
// when
|
||||
ResponseEntity<CommentResponseDto> responseEntity = restTemplate.exchange(
|
||||
URL,
|
||||
HttpMethod.PUT,
|
||||
httpEntity,
|
||||
new ParameterizedTypeReference<CommentResponseDto>() {
|
||||
}
|
||||
);
|
||||
|
||||
// then
|
||||
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
|
||||
CommentResponseDto dto = responseEntity.getBody();
|
||||
assertThat(dto).isNotNull();
|
||||
|
||||
Optional<Comment> comment = selectData(boardNo, postsNo, commentNo);
|
||||
assertThat(comment).isPresent();
|
||||
|
||||
Comment updatedComment = comment.get();
|
||||
assertThat(updatedComment.getCommentId().getPostsId().getBoardNo()).isEqualTo(boardNo);
|
||||
assertThat(updatedComment.getCommentId().getPostsId().getPostsNo()).isEqualTo(postsNo);
|
||||
assertThat(updatedComment.getCommentId().getCommentNo()).isEqualTo(commentNo);
|
||||
assertThat(updatedComment.getCommentContent()).isEqualTo(UPDATE_COMMENT_CONTENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* 댓글 삭제
|
||||
*/
|
||||
@Test
|
||||
void 댓글_삭제() {
|
||||
log.info("###댓글_삭제");
|
||||
|
||||
// given
|
||||
Comment entity = insertComment();
|
||||
|
||||
final Integer boardNo = entity.getCommentId().getPostsId().getBoardNo();
|
||||
final Integer postsNo = entity.getCommentId().getPostsId().getPostsNo();
|
||||
final Integer commentNo = entity.getCommentId().getCommentNo();
|
||||
|
||||
String url = URL + "/" + boardNo + "/" + postsNo + "/" + commentNo;
|
||||
|
||||
// when
|
||||
ResponseEntity<BoardResponseDto> responseEntity = restTemplate.exchange(
|
||||
url,
|
||||
HttpMethod.DELETE,
|
||||
null,
|
||||
BoardResponseDto.class
|
||||
);
|
||||
|
||||
// then
|
||||
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
|
||||
Optional<Comment> comment = selectData(boardNo, postsNo, commentNo);
|
||||
assertThat(comment).isPresent();
|
||||
|
||||
Comment deletedComment = comment.get();
|
||||
assertThat(deletedComment.getCommentId().getPostsId().getBoardNo()).isEqualTo(boardNo);
|
||||
assertThat(deletedComment.getCommentId().getPostsId().getPostsNo()).isEqualTo(postsNo);
|
||||
assertThat(deletedComment.getCommentId().getCommentNo()).isEqualTo(commentNo);
|
||||
assertThat(deletedComment.getDeleteAt()).isNotZero();
|
||||
}
|
||||
|
||||
/**
|
||||
* 테스트 데이터 등록
|
||||
*/
|
||||
private void insertComments() {
|
||||
log.info("###테스트 데이터 등록");
|
||||
|
||||
// 댓글 등록
|
||||
List<Comment> list = new ArrayList<>();
|
||||
for (int i = 1; i <= GIVEN_DATA_COUNT; i++) {
|
||||
list.add(Comment.builder()
|
||||
.posts(posts)
|
||||
.commentId(CommentId.builder()
|
||||
.postsId(PostsId.builder()
|
||||
.boardNo(posts.getPostsId().getBoardNo())
|
||||
.postsNo(posts.getPostsId().getPostsNo())
|
||||
.build())
|
||||
.commentNo(i)
|
||||
.build())
|
||||
.commentContent(INSERT_COMMENT_CONTENT + i)
|
||||
.groupNo(i)
|
||||
.depthSeq(0)
|
||||
.sortSeq(i)
|
||||
.deleteAt(i % 3)
|
||||
.build());
|
||||
}
|
||||
|
||||
commentRepository.saveAll(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 테스트 데이터 단건 등록
|
||||
*
|
||||
* @return Comment 댓글 엔티티
|
||||
*/
|
||||
private Comment insertComment() {
|
||||
log.info("###테스트 데이터 단건 등록");
|
||||
|
||||
return commentRepository.save(Comment.builder()
|
||||
.posts(posts)
|
||||
.commentId(CommentId.builder()
|
||||
.postsId(PostsId.builder()
|
||||
.boardNo(posts.getPostsId().getBoardNo())
|
||||
.postsNo(posts.getPostsId().getPostsNo())
|
||||
.build())
|
||||
.commentNo(INSERT_COMMENT_NO)
|
||||
.build())
|
||||
.commentContent(INSERT_COMMENT_CONTENT)
|
||||
.groupNo(INSERT_COMMENT_NO)
|
||||
.depthSeq(0)
|
||||
.sortSeq(INSERT_COMMENT_NO)
|
||||
.deleteAt(0)
|
||||
.build());
|
||||
}
|
||||
|
||||
/**
|
||||
* 테스트 데이터 단건 삭제
|
||||
*/
|
||||
/*private void deleteComment(Comment comment) {
|
||||
log.info("###테스트 데이터 단건 삭제");
|
||||
|
||||
commentRepository.deleteById(comment.getCommentId());
|
||||
}*/
|
||||
|
||||
/**
|
||||
* 테스트 데이터 삭제
|
||||
*/
|
||||
/*private void deleteComments() {
|
||||
log.info("###테스트 데이터 삭제");
|
||||
|
||||
commentRepository.deleteAll(comments);
|
||||
|
||||
comments.clear();
|
||||
}*/
|
||||
|
||||
/**
|
||||
* 테스트 데이터 단건 조회
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @param commentNo 댓글 번호
|
||||
* @return Optional<Comment> 댓글 엔티티
|
||||
*/
|
||||
private Optional<Comment> selectData(Integer boardNo, Integer postsNo, Integer commentNo) {
|
||||
log.info("###테스트 데이터 단건 조회");
|
||||
|
||||
return commentRepository.findById(CommentId.builder()
|
||||
.postsId(PostsId.builder()
|
||||
.boardNo(boardNo)
|
||||
.postsNo(postsNo)
|
||||
.build())
|
||||
.commentNo(commentNo)
|
||||
.build());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,730 @@
|
||||
package org.egovframe.cloud.boardservice.api.posts;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.assertj.core.api.Condition;
|
||||
import org.egovframe.cloud.boardservice.api.posts.dto.PostsListResponseDto;
|
||||
import org.egovframe.cloud.boardservice.api.posts.dto.PostsResponseDto;
|
||||
import org.egovframe.cloud.boardservice.domain.board.Board;
|
||||
import org.egovframe.cloud.boardservice.domain.board.BoardRepository;
|
||||
import org.egovframe.cloud.boardservice.domain.posts.Posts;
|
||||
import org.egovframe.cloud.boardservice.domain.posts.PostsId;
|
||||
import org.egovframe.cloud.boardservice.domain.posts.PostsRepository;
|
||||
import org.egovframe.cloud.boardservice.util.RestResponsePage;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.JsonMappingException;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.boardservice.api.posts.PostsApiControllerTest
|
||||
* <p>
|
||||
* 게시물 Rest API 컨트롤러 클래스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/08/10
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/08/10 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
@Slf4j
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||
@EnableConfigurationProperties
|
||||
@TestPropertySource(properties = {"spring.config.location=classpath:application-test.yml"})
|
||||
@ActiveProfiles(profiles = "test")
|
||||
class PostsApiControllerTest {
|
||||
|
||||
/**
|
||||
* test rest template
|
||||
*/
|
||||
@Autowired
|
||||
TestRestTemplate restTemplate;
|
||||
|
||||
/**
|
||||
* 게시판 레파지토리 인터페이스
|
||||
*/
|
||||
@Autowired
|
||||
BoardRepository boardRepository;
|
||||
|
||||
/**
|
||||
* 게시물 레파지토리 인터페이스
|
||||
*/
|
||||
@Autowired
|
||||
PostsRepository postsRepository;
|
||||
|
||||
/**
|
||||
* 게시물 API 경로
|
||||
*/
|
||||
private static final String URL = "/api/v1/posts";
|
||||
|
||||
/**
|
||||
* 테스트 데이터 등록 횟수
|
||||
*/
|
||||
private final Integer GIVEN_DATA_COUNT = 10;
|
||||
|
||||
/**
|
||||
* 테스트 데이터
|
||||
*/
|
||||
private Board board;
|
||||
private List<Posts> posts = new ArrayList<>();
|
||||
|
||||
private final Integer INSERT_POSTS_NO = 1;
|
||||
private final String INSERT_POSTS_TITLE = "게시물 제목";
|
||||
private final String INSERT_POSTS_CONTENT = "게시물 내용";
|
||||
private final String INSERT_POSTS_ANSWER_CONTENT = "게시물 답변 내용";
|
||||
private final String INSERT_ATTACHMENT_CODE = "0000000001";
|
||||
private final Integer INSERT_READ_COUNT = 0;
|
||||
private final Boolean INSERT_NOTICE_AT = true;
|
||||
|
||||
private final String UPDATE_POSTS_TITLE = "게시물 제목 수정";
|
||||
private final String UPDATE_POSTS_CONTENT = "게시물 내용 수정";
|
||||
private final String UPDATE_POSTS_ANSWER_CONTENT = "게시물 답변 내용 수정";
|
||||
private final String UPDATE_ATTACHMENT_CODE = "0000000002";
|
||||
private final Boolean UPDATE_NOTICE_AT = false;
|
||||
|
||||
/**
|
||||
* 테스트 시작 전 수행
|
||||
*/
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
log.info("###setUp");
|
||||
|
||||
// 게시판 등록
|
||||
board = boardRepository.save(Board.builder()
|
||||
.boardName("일반게시판1")
|
||||
.skinTypeCode("normal")
|
||||
.titleDisplayLength(50)
|
||||
.postDisplayCount(50)
|
||||
.pageDisplayCount(50)
|
||||
.newDisplayDayCount(50)
|
||||
.editorUseAt(true)
|
||||
.uploadUseAt(true)
|
||||
.uploadLimitCount(50)
|
||||
.uploadLimitSize(new BigDecimal("52428800"))
|
||||
.userWriteAt(false)
|
||||
.commentUseAt(true)
|
||||
.build());
|
||||
}
|
||||
|
||||
/**
|
||||
* 테스트 종료 후 수행
|
||||
*/
|
||||
@AfterEach
|
||||
void tearDown() {
|
||||
log.info("###tearDown");
|
||||
|
||||
postsRepository.deleteAll();
|
||||
|
||||
// 게시판 삭제
|
||||
boardRepository.deleteAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* 최근 게시물이 포함된 게시판 목록 조회
|
||||
* @throws JsonProcessingException json exception
|
||||
* @throws JsonMappingException json exception
|
||||
*/
|
||||
@Test
|
||||
void 최근_게시물이_포함된_게시판_목록_조회() throws JsonMappingException, JsonProcessingException {
|
||||
log.info("###최근_게시물이_포함된_게시판_목록_조회");
|
||||
|
||||
// given
|
||||
insertPosts(null);
|
||||
|
||||
final Integer postsCount = 3;
|
||||
final String url = URL + "/newest/" + board.getBoardNo() + "/" + postsCount;
|
||||
|
||||
// when
|
||||
ResponseEntity<String> responseEntity = restTemplate.exchange(
|
||||
url,
|
||||
HttpMethod.GET,
|
||||
null,
|
||||
new ParameterizedTypeReference<String>() {
|
||||
}
|
||||
);
|
||||
|
||||
// then
|
||||
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
JsonNode data = mapper.readTree(responseEntity.getBody());
|
||||
JsonNode boardData = data.get(board.getBoardNo().toString());
|
||||
|
||||
assertThat(data).isNotNull();
|
||||
assertThat(boardData.get("boardNo").asInt()).isEqualTo(board.getBoardNo());
|
||||
assertThat(boardData.get("posts").isArray()).isTrue();
|
||||
// assertThat(boardData.get("posts").size()).isEqualTo(postsCount); // h2에서 rownum을 계산하지 못해서 3건, 5건 조회될때가 있음.
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물 삭제포함 페이지 목록 조회
|
||||
*/
|
||||
@Test
|
||||
void 게시물_삭제포함_페이지_목록_조회() {
|
||||
log.info("###게시물_삭제포함_페이지_목록_조회");
|
||||
|
||||
// given
|
||||
insertPosts(null);
|
||||
|
||||
String url = URL + "/" + board.getBoardNo();
|
||||
String queryString = "?keywordType=postsTitle&keyword=" + INSERT_POSTS_TITLE; // 검색 조건
|
||||
queryString += "&page=0&size=" + GIVEN_DATA_COUNT; // 페이지 정보
|
||||
|
||||
// when
|
||||
ResponseEntity<RestResponsePage<PostsListResponseDto>> responseEntity = restTemplate.exchange(
|
||||
url + queryString,
|
||||
HttpMethod.GET,
|
||||
null,
|
||||
new ParameterizedTypeReference<RestResponsePage<PostsListResponseDto>>() {
|
||||
}
|
||||
);
|
||||
|
||||
// then
|
||||
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
|
||||
RestResponsePage<PostsListResponseDto> page = responseEntity.getBody();
|
||||
assertThat(page).isNotNull();
|
||||
assertThat(page.getNumberOfElements()).isEqualTo(GIVEN_DATA_COUNT);
|
||||
assertThat(page.getContent())
|
||||
.isNotEmpty()
|
||||
.has(new Condition<>(l -> (INSERT_POSTS_TITLE + "9").equals(l.get(0).getPostsTitle()) && l.get(0).getNoticeAt(), "PostsApiControllerTest.findPage contains [notice] " + INSERT_POSTS_TITLE + "9"))
|
||||
.has(new Condition<>(l -> (INSERT_POSTS_TITLE + "6").equals(l.get(1).getPostsTitle()) && l.get(0).getNoticeAt(), "PostsApiControllerTest.findPage contains [notice] " + INSERT_POSTS_TITLE + "6"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물 삭제제외 페이지 목록 조회
|
||||
*/
|
||||
@Test
|
||||
void 게시물_삭제제외_페이지_목록_조회() {
|
||||
log.info("###게시물_삭제제외_페이지_목록_조회");
|
||||
|
||||
// given
|
||||
insertPosts(null);
|
||||
|
||||
String url = URL + "/list/" + board.getBoardNo();
|
||||
String queryString = "?keywordType=postsTitle&keyword=" + INSERT_POSTS_TITLE; // 검색 조건
|
||||
queryString += "&page=0&size=" + GIVEN_DATA_COUNT; // 페이지 정보
|
||||
|
||||
// when
|
||||
ResponseEntity<RestResponsePage<PostsListResponseDto>> responseEntity = restTemplate.exchange(
|
||||
url + queryString,
|
||||
HttpMethod.GET,
|
||||
null,
|
||||
new ParameterizedTypeReference<RestResponsePage<PostsListResponseDto>>() {
|
||||
}
|
||||
);
|
||||
|
||||
// then
|
||||
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
|
||||
RestResponsePage<PostsListResponseDto> page = responseEntity.getBody();
|
||||
assertThat(page).isNotNull();
|
||||
assertThat(page.getNumberOfElements()).isEqualTo(GIVEN_DATA_COUNT / 2);
|
||||
assertThat(page.getContent())
|
||||
.isNotEmpty()
|
||||
.has(new Condition<>(l -> (INSERT_POSTS_TITLE + "6").equals(l.get(0).getPostsTitle()) && l.get(0).getNoticeAt(), "PostsApiControllerTest.findPage contains [notice] " + INSERT_POSTS_TITLE + "6"))
|
||||
.has(new Condition<>(l -> (INSERT_POSTS_TITLE + "10").equals(l.get(1).getPostsTitle()) && l.get(0).getNoticeAt(), "PostsApiControllerTest.findPage contains [notice] " + INSERT_POSTS_TITLE + "10"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물 삭제포함 단건 조회
|
||||
*/
|
||||
@Test
|
||||
void 게시물_삭제포함_단건_조회() {
|
||||
log.info("###게시물_삭제포함_단건_조회");
|
||||
|
||||
// given
|
||||
final Posts post = insertPost(1);
|
||||
|
||||
String url = URL + "/" + post.getPostsId().getBoardNo() + "/" + post.getPostsId().getPostsNo();
|
||||
|
||||
// when
|
||||
ResponseEntity<PostsResponseDto> responseEntity = restTemplate.exchange(
|
||||
url,
|
||||
HttpMethod.GET,
|
||||
null,
|
||||
new ParameterizedTypeReference<PostsResponseDto>() {
|
||||
}
|
||||
);
|
||||
|
||||
// then
|
||||
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
|
||||
PostsResponseDto dto = responseEntity.getBody();
|
||||
assertThat(dto).isNotNull();
|
||||
assertThat(dto.getBoardNo()).isEqualTo(post.getPostsId().getBoardNo());
|
||||
assertThat(dto.getPostsNo()).isEqualTo(post.getPostsId().getPostsNo());
|
||||
assertThat(dto.getPostsTitle()).isEqualTo(post.getPostsTitle());
|
||||
assertThat(dto.getPostsContent()).isEqualTo(post.getPostsContent());
|
||||
assertThat(dto.getPostsAnswerContent()).isEqualTo(post.getPostsAnswerContent());
|
||||
assertThat(dto.getAttachmentCode()).isEqualTo(post.getAttachmentCode());
|
||||
assertThat(dto.getReadCount()).isEqualTo(post.getReadCount() + 1);
|
||||
assertThat(dto.getNoticeAt()).isEqualTo(post.getNoticeAt());
|
||||
assertThat(dto.getDeleteAt()).isEqualTo(post.getDeleteAt());
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물 삭제제외 단건 조회
|
||||
*/
|
||||
@Test
|
||||
void 게시물_삭제제외_단건_조회() {
|
||||
log.info("###게시물_삭제제외_단건_조회");
|
||||
|
||||
// given
|
||||
final Posts post = insertPost(1);
|
||||
|
||||
String url = URL + "/view/" + post.getPostsId().getBoardNo() + "/" + post.getPostsId().getPostsNo();
|
||||
|
||||
// when
|
||||
ResponseEntity<PostsResponseDto> responseEntity = restTemplate.exchange(
|
||||
url,
|
||||
HttpMethod.GET,
|
||||
null,
|
||||
new ParameterizedTypeReference<PostsResponseDto>() {
|
||||
}
|
||||
);
|
||||
|
||||
// then
|
||||
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST); // 삭제 게시물 조회 불가
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물 등록 작성자체크
|
||||
*/
|
||||
@Test
|
||||
void 게시물_등록_작성자체크() {
|
||||
log.info("###게시물_등록_작성자체크");
|
||||
|
||||
// given
|
||||
String url = URL + "/save/" + board.getBoardNo();
|
||||
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("postsTitle", INSERT_POSTS_TITLE);
|
||||
params.put("postsContent", INSERT_POSTS_CONTENT);
|
||||
params.put("postsAnswerContent", INSERT_POSTS_ANSWER_CONTENT);
|
||||
params.put("attachmentCode", INSERT_ATTACHMENT_CODE);
|
||||
params.put("noticeAt", INSERT_NOTICE_AT);
|
||||
HttpEntity<Map<String, Object>> httpEntity = new HttpEntity<>(params);
|
||||
|
||||
// when
|
||||
ResponseEntity<PostsResponseDto> responseEntity = restTemplate.exchange(
|
||||
url,
|
||||
HttpMethod.POST,
|
||||
httpEntity,
|
||||
new ParameterizedTypeReference<PostsResponseDto>() {
|
||||
}
|
||||
);
|
||||
|
||||
// then
|
||||
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST); // 게시판에 사용자 글쓰기 허용 X
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물 수정 작성자체크
|
||||
*/
|
||||
@Test
|
||||
void 게시물_수정_작성자체크() {
|
||||
log.info("###게시물_수정 작성자체크");
|
||||
|
||||
// given
|
||||
Posts entity = insertPost(0);
|
||||
|
||||
final Integer boardNo = entity.getPostsId().getBoardNo();
|
||||
final Integer postsNo = entity.getPostsId().getPostsNo();
|
||||
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("postsTitle", UPDATE_POSTS_TITLE);
|
||||
params.put("postsContent", UPDATE_POSTS_CONTENT);
|
||||
params.put("postsAnswerContent", UPDATE_POSTS_ANSWER_CONTENT);
|
||||
params.put("attachmentCode", UPDATE_ATTACHMENT_CODE);
|
||||
params.put("noticeAt", UPDATE_NOTICE_AT);
|
||||
HttpEntity<Map<String, Object>> httpEntity = new HttpEntity<>(params);
|
||||
|
||||
String url = URL + "/update/" + boardNo + "/" + postsNo;
|
||||
|
||||
// when
|
||||
ResponseEntity<PostsResponseDto> responseEntity = restTemplate.exchange(
|
||||
url,
|
||||
HttpMethod.PUT,
|
||||
httpEntity,
|
||||
new ParameterizedTypeReference<PostsResponseDto>() {
|
||||
}
|
||||
);
|
||||
|
||||
// then
|
||||
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST); // 본인글 아닌 경우 예외 발생
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물 삭제 작성자체크
|
||||
*/
|
||||
@Test
|
||||
void 게시물_삭제_작성자체크() {
|
||||
log.info("###게시물_삭제 작성자체크");
|
||||
|
||||
// given
|
||||
Posts entity = insertPost(0);
|
||||
|
||||
final Integer boardNo = entity.getPostsId().getBoardNo();
|
||||
final Integer postsNo = entity.getPostsId().getPostsNo();
|
||||
|
||||
String url = URL + "/remove/" + boardNo + "/" + postsNo;
|
||||
|
||||
// when
|
||||
ResponseEntity<Void> responseEntity = restTemplate.exchange(
|
||||
url,
|
||||
HttpMethod.DELETE,
|
||||
null,
|
||||
new ParameterizedTypeReference<Void>() {
|
||||
}
|
||||
);
|
||||
|
||||
// then
|
||||
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST); // 본인글 아닌 경우 예외 발생
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물 등록
|
||||
*/
|
||||
@Test
|
||||
void 게시물_등록() {
|
||||
log.info("###게시물_등록");
|
||||
|
||||
// given
|
||||
String url = URL + "/" + board.getBoardNo();
|
||||
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("postsTitle", INSERT_POSTS_TITLE);
|
||||
params.put("postsContent", INSERT_POSTS_CONTENT);
|
||||
params.put("postsAnswerContent", INSERT_POSTS_ANSWER_CONTENT);
|
||||
params.put("attachmentCode", INSERT_ATTACHMENT_CODE);
|
||||
params.put("noticeAt", INSERT_NOTICE_AT);
|
||||
HttpEntity<Map<String, Object>> httpEntity = new HttpEntity<>(params);
|
||||
|
||||
// when
|
||||
ResponseEntity<PostsResponseDto> responseEntity = restTemplate.exchange(
|
||||
url,
|
||||
HttpMethod.POST,
|
||||
httpEntity,
|
||||
new ParameterizedTypeReference<PostsResponseDto>() {
|
||||
}
|
||||
);
|
||||
|
||||
// then
|
||||
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
|
||||
PostsResponseDto dto = responseEntity.getBody();
|
||||
assertThat(dto).isNotNull();
|
||||
|
||||
final Integer boardNo = dto.getBoardNo();
|
||||
final Integer postsNo = dto.getPostsNo();
|
||||
|
||||
Optional<Posts> posts = selectData(boardNo, postsNo);
|
||||
assertThat(posts).isPresent();
|
||||
|
||||
Posts entity = posts.get();
|
||||
assertThat(entity.getPostsId().getBoardNo()).isEqualTo(boardNo);
|
||||
assertThat(entity.getPostsId().getPostsNo()).isEqualTo(postsNo);
|
||||
assertThat(entity.getPostsTitle()).isEqualTo(INSERT_POSTS_TITLE);
|
||||
assertThat(entity.getPostsContent()).isEqualTo(INSERT_POSTS_CONTENT);
|
||||
assertThat(entity.getPostsAnswerContent()).isEqualTo(INSERT_POSTS_ANSWER_CONTENT);
|
||||
assertThat(entity.getAttachmentCode()).isEqualTo(INSERT_ATTACHMENT_CODE);
|
||||
assertThat(entity.getReadCount()).isZero();
|
||||
assertThat(entity.getNoticeAt()).isEqualTo(INSERT_NOTICE_AT);
|
||||
assertThat(entity.getDeleteAt()).isZero();
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물 수정
|
||||
*/
|
||||
@Test
|
||||
void 게시물_수정() {
|
||||
log.info("###게시물_수정");
|
||||
|
||||
// given
|
||||
Posts entity = insertPost(0);
|
||||
|
||||
final Integer boardNo = entity.getPostsId().getBoardNo();
|
||||
final Integer postsNo = entity.getPostsId().getPostsNo();
|
||||
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("postsTitle", UPDATE_POSTS_TITLE);
|
||||
params.put("postsContent", UPDATE_POSTS_CONTENT);
|
||||
params.put("postsAnswerContent", UPDATE_POSTS_ANSWER_CONTENT);
|
||||
params.put("attachmentCode", UPDATE_ATTACHMENT_CODE);
|
||||
params.put("noticeAt", UPDATE_NOTICE_AT);
|
||||
HttpEntity<Map<String, Object>> httpEntity = new HttpEntity<>(params);
|
||||
|
||||
String url = URL + "/" + boardNo + "/" + postsNo;
|
||||
|
||||
// when
|
||||
ResponseEntity<PostsResponseDto> responseEntity = restTemplate.exchange(
|
||||
url,
|
||||
HttpMethod.PUT,
|
||||
httpEntity,
|
||||
new ParameterizedTypeReference<PostsResponseDto>() {
|
||||
}
|
||||
);
|
||||
|
||||
// then
|
||||
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
|
||||
PostsResponseDto dto = responseEntity.getBody();
|
||||
assertThat(dto).isNotNull();
|
||||
|
||||
Optional<Posts> posts = selectData(boardNo, postsNo);
|
||||
assertThat(posts).isPresent();
|
||||
|
||||
Posts updatedPosts = posts.get();
|
||||
assertThat(updatedPosts.getPostsId().getBoardNo()).isEqualTo(boardNo);
|
||||
assertThat(updatedPosts.getPostsId().getPostsNo()).isEqualTo(postsNo);
|
||||
assertThat(updatedPosts.getPostsTitle()).isEqualTo(UPDATE_POSTS_TITLE);
|
||||
assertThat(updatedPosts.getPostsContent()).isEqualTo(UPDATE_POSTS_CONTENT);
|
||||
assertThat(updatedPosts.getPostsAnswerContent()).isEqualTo(UPDATE_POSTS_ANSWER_CONTENT);
|
||||
assertThat(updatedPosts.getAttachmentCode()).isEqualTo(UPDATE_ATTACHMENT_CODE);
|
||||
assertThat(updatedPosts.getNoticeAt()).isEqualTo(UPDATE_NOTICE_AT);
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물 다건 삭제
|
||||
*/
|
||||
@Test
|
||||
void 게시물_다건_삭제() {
|
||||
log.info("###게시물_다건_삭제");
|
||||
|
||||
// given
|
||||
insertPosts(false);
|
||||
|
||||
List<Map<String, Object>> params = new ArrayList<>();
|
||||
for (Posts post : posts) {
|
||||
Map<String, Object> param = new HashMap<>();
|
||||
param.put("boardNo", post.getPostsId().getBoardNo());
|
||||
param.put("postsNo", post.getPostsId().getPostsNo());
|
||||
|
||||
params.add(param);
|
||||
}
|
||||
|
||||
HttpEntity<List<Map<String, Object>>> httpEntity = new HttpEntity<>(params);
|
||||
|
||||
String url = URL + "/remove";
|
||||
|
||||
// when
|
||||
ResponseEntity<Long> responseEntity = restTemplate.exchange(
|
||||
url,
|
||||
HttpMethod.PUT,
|
||||
httpEntity,
|
||||
Long.class
|
||||
);
|
||||
|
||||
// then
|
||||
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
assertThat(responseEntity.getBody()).isEqualTo(posts.size());
|
||||
|
||||
List<Posts> list = postsRepository.findAll();
|
||||
|
||||
assertThat(list).isNotNull();
|
||||
assertThat(list.size()).isEqualTo(posts.size());
|
||||
|
||||
for (Posts post : list) {
|
||||
assertThat(post).isNotNull();
|
||||
assertThat(post.getDeleteAt()).isNotZero();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물 다건 복원
|
||||
*/
|
||||
@Test
|
||||
void 게시물_다건_복원() {
|
||||
log.info("###게시물_다건_복원");
|
||||
|
||||
// given
|
||||
insertPosts(true);
|
||||
|
||||
List<Map<String, Object>> params = new ArrayList<>();
|
||||
for (Posts post : posts) {
|
||||
Map<String, Object> param = new HashMap<>();
|
||||
param.put("boardNo", post.getPostsId().getBoardNo());
|
||||
param.put("postsNo", post.getPostsId().getPostsNo());
|
||||
|
||||
params.add(param);
|
||||
}
|
||||
|
||||
HttpEntity<List<Map<String, Object>>> httpEntity = new HttpEntity<>(params);
|
||||
|
||||
String url = URL + "/restore";
|
||||
|
||||
// when
|
||||
ResponseEntity<Long> responseEntity = restTemplate.exchange(
|
||||
url,
|
||||
HttpMethod.PUT,
|
||||
httpEntity,
|
||||
Long.class
|
||||
);
|
||||
|
||||
// then
|
||||
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
assertThat(responseEntity.getBody()).isEqualTo(posts.size());
|
||||
|
||||
List<Posts> list = postsRepository.findAll();
|
||||
|
||||
assertThat(list).isNotNull();
|
||||
assertThat(list.size()).isEqualTo(posts.size());
|
||||
|
||||
for (Posts post : list) {
|
||||
assertThat(post).isNotNull();
|
||||
assertThat(post.getDeleteAt()).isZero();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 게시물 다건 완전 삭제
|
||||
*/
|
||||
@Test
|
||||
void 게시물_다건_완전_삭제() {
|
||||
log.info("###게시물_다건_완전_삭제");
|
||||
|
||||
// given
|
||||
insertPosts(null);
|
||||
|
||||
List<Map<String, Object>> params = new ArrayList<>();
|
||||
for (Posts post : posts) {
|
||||
Map<String, Object> param = new HashMap<>();
|
||||
param.put("boardNo", post.getPostsId().getBoardNo());
|
||||
param.put("postsNo", post.getPostsId().getPostsNo());
|
||||
|
||||
params.add(param);
|
||||
}
|
||||
|
||||
HttpEntity<List<Map<String, Object>>> httpEntity = new HttpEntity<>(params);
|
||||
|
||||
String url = URL + "/delete";
|
||||
|
||||
// when
|
||||
ResponseEntity<Long> responseEntity = restTemplate.exchange(
|
||||
url,
|
||||
HttpMethod.PUT,
|
||||
httpEntity,
|
||||
Long.class
|
||||
);
|
||||
|
||||
// then
|
||||
assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
|
||||
List<Posts> list = postsRepository.findAll();
|
||||
|
||||
assertThat(list).isNotNull();
|
||||
assertThat(list.size()).isZero();
|
||||
}
|
||||
|
||||
/**
|
||||
* 테스트 데이터 등록
|
||||
*/
|
||||
private void insertPosts(Boolean deleteAt) {
|
||||
log.info("###테스트 데이터 등록");
|
||||
|
||||
// 게시물 등록
|
||||
List<Posts> list = new ArrayList<>();
|
||||
for (int i = 1; i <= GIVEN_DATA_COUNT; i++) {
|
||||
list.add(Posts.builder()
|
||||
.board(board)
|
||||
.postsId(PostsId.builder()
|
||||
.boardNo(board.getBoardNo())
|
||||
.postsNo(i)
|
||||
.build())
|
||||
.postsTitle(INSERT_POSTS_TITLE + i)
|
||||
.postsContent(INSERT_POSTS_CONTENT + i)
|
||||
.postsAnswerContent(INSERT_POSTS_ANSWER_CONTENT + i)
|
||||
.attachmentCode(StringUtils.leftPad(String.valueOf(i), 10, '0'))
|
||||
.readCount(0)
|
||||
.noticeAt(i % 3 == 0)
|
||||
.deleteAt(i % 2)
|
||||
.build());
|
||||
}
|
||||
|
||||
posts = postsRepository.saveAll(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 테스트 데이터 단건 등록
|
||||
*
|
||||
* @return Posts 게시물 엔티티
|
||||
*/
|
||||
private Posts insertPost(Integer deleteAt) {
|
||||
log.info("###테스트 데이터 단건 등록");
|
||||
|
||||
return postsRepository.save(Posts.builder()
|
||||
.board(board)
|
||||
.postsId(PostsId.builder()
|
||||
.boardNo(board.getBoardNo())
|
||||
.postsNo(INSERT_POSTS_NO)
|
||||
.build())
|
||||
.postsTitle(INSERT_POSTS_TITLE + 1)
|
||||
.postsContent(INSERT_POSTS_CONTENT + 1)
|
||||
.postsAnswerContent(INSERT_POSTS_ANSWER_CONTENT + 1)
|
||||
.attachmentCode(INSERT_ATTACHMENT_CODE)
|
||||
.readCount(INSERT_READ_COUNT)
|
||||
.noticeAt(INSERT_NOTICE_AT)
|
||||
.deleteAt(deleteAt)
|
||||
.build());
|
||||
}
|
||||
|
||||
/**
|
||||
* 테스트 데이터 단건 삭제
|
||||
*/
|
||||
/*private void deletePost(Posts post) {
|
||||
postsRepository.deleteById(post.getPostsId());
|
||||
}*/
|
||||
|
||||
/**
|
||||
* 테스트 데이터 삭제
|
||||
*/
|
||||
/*private void deletePosts() {
|
||||
postsRepository.deleteAll(posts);
|
||||
|
||||
posts.clear();
|
||||
}*/
|
||||
|
||||
/**
|
||||
* 테스트 데이터 단건 조회
|
||||
*
|
||||
* @param boardNo 게시판 번호
|
||||
* @param postsNo 게시물 번호
|
||||
* @return Optional<Posts> 게시물 엔티티
|
||||
*/
|
||||
private Optional<Posts> selectData(Integer boardNo, Integer postsNo) {
|
||||
return postsRepository.findById(PostsId.builder().boardNo(boardNo).postsNo(postsNo).build());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package org.egovframe.cloud.boardservice.util;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.domain.PageImpl;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
|
||||
/**
|
||||
* org.egovframe.cloud.boardservice.util.RestResponsePage
|
||||
* <p>
|
||||
* 페이지 API 조회 시 JSON 형식의 응답 데이터를 페이지 객체를 구현하여 마이그레이션 해주는 클래스
|
||||
*
|
||||
* @author 표준프레임워크센터 jooho
|
||||
* @version 1.0
|
||||
* @since 2021/07/08
|
||||
*
|
||||
* <pre>
|
||||
* << 개정이력(Modification Information) >>
|
||||
*
|
||||
* 수정일 수정자 수정내용
|
||||
* ---------- -------- ---------------------------
|
||||
* 2021/07/08 jooho 최초 생성
|
||||
* </pre>
|
||||
*/
|
||||
public class RestResponsePage<T> extends PageImpl<T> {
|
||||
|
||||
/**
|
||||
* serialVersionUID
|
||||
*/
|
||||
private static final long serialVersionUID = -4377617807230211193L;
|
||||
|
||||
/**
|
||||
* Rest 응답 페이지 생성자
|
||||
*
|
||||
* @param content 목록
|
||||
* @param number 페이지 번호
|
||||
* @param size 조회할 데이터 수
|
||||
* @param totalElements 총 데이터 수
|
||||
* @param pageable 페이지 정보
|
||||
* @param last 마지막
|
||||
* @param totalPages 총 페이지
|
||||
* @param sort 정렬
|
||||
* @param first 처음
|
||||
* @param numberOfElements 조회된 데이터 수
|
||||
*/
|
||||
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
|
||||
public RestResponsePage(@JsonProperty("content") List<T> content,
|
||||
@JsonProperty("number") int number,
|
||||
@JsonProperty("size") int size,
|
||||
@JsonProperty("totalElements") Long totalElements,
|
||||
@JsonProperty("pageable") JsonNode pageable,
|
||||
@JsonProperty("last") boolean last,
|
||||
@JsonProperty("totalPages") int totalPages,
|
||||
@JsonProperty("sort") JsonNode sort,
|
||||
@JsonProperty("first") boolean first,
|
||||
@JsonProperty("numberOfElements") int numberOfElements) {
|
||||
super(content, PageRequest.of(number, size), totalElements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rest 응답 페이지 생성자
|
||||
*
|
||||
* @param content 목록
|
||||
* @param pageable 페이지 정보
|
||||
* @param total 총 데이터 수
|
||||
*/
|
||||
public RestResponsePage(List<T> content, Pageable pageable, long total) {
|
||||
super(content, pageable, total);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rest 응답 페이지 생성자
|
||||
*
|
||||
* @param content 목록
|
||||
*/
|
||||
public RestResponsePage(List<T> content) {
|
||||
super(content);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rest 응답 페이지 생성자
|
||||
*/
|
||||
public RestResponsePage() {
|
||||
super(Collections.emptyList());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
spring:
|
||||
application:
|
||||
name: board-service
|
||||
|
||||
datasource:
|
||||
url: jdbc:h2:mem:testdb;MODE=MYSQL;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false
|
||||
username: sa
|
||||
password:
|
||||
driver-class-name: org.h2.Driver
|
||||
jpa:
|
||||
# database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
|
||||
hibernate:
|
||||
generate-ddl: true
|
||||
ddl-auto: create-drop
|
||||
# dialect: org.hibernate.dialect.MySQL5InnoDBDialect
|
||||
properties:
|
||||
hibernate:
|
||||
format_sql: true
|
||||
default_batch_fetch_size: 1000
|
||||
show-sql: true
|
||||
h2:
|
||||
console:
|
||||
enabled: true
|
||||
path: /h2
|
||||
|
||||
logging.level:
|
||||
org.hibernate.SQL: debug
|
||||
|
||||
file:
|
||||
directory: ${user.home}/msa-attach-volume
|
||||
messages:
|
||||
directory: ${file.directory}/messages
|
||||
|
||||
# jwt token
|
||||
token:
|
||||
secret: egovframe_user_token
|
||||
|
||||
# ftp server
|
||||
ftp:
|
||||
enabled: false # ftp 사용 여부, FTP 서버에 최상위 디렉토리 자동 생성 및 구현체를 결정하게 된다.
|
||||
|
||||
# eureka 가 포함되면 eureka server 도 등록되므로 해제한다.
|
||||
eureka:
|
||||
client:
|
||||
register-with-eureka: false
|
||||
fetch-registry: false
|
||||
Reference in New Issue
Block a user