├── LICENSE ├── README.md ├── mvnw ├── mvnw.cmd ├── pom.xml └── src ├── main ├── java │ └── com │ │ └── sw │ │ └── project │ │ ├── ProjectApiApplication.java │ │ ├── aspect │ │ └── RestControllerAspect.java │ │ ├── config │ │ └── JpaConfiguration.java │ │ ├── controller │ │ ├── ProblemController.java │ │ ├── ProjectController.java │ │ └── subProblemController.java │ │ ├── domain │ │ ├── AuditModel.java │ │ ├── LocalDateAttributeConverter.java │ │ ├── LocalDateTimeAttributeConverter.java │ │ ├── Problem.java │ │ ├── Project.java │ │ ├── subProblem.java │ │ └── subProblemBody.java │ │ ├── exception │ │ ├── CustmizeExceptionHandler.java │ │ ├── CustomizeErrorDetail.java │ │ ├── DataFormatException.java │ │ ├── ElementNullException.java │ │ ├── InternerServerError.java │ │ ├── NotDefineException.java │ │ ├── NullPointerException.java │ │ └── ResourceNotFoundException.java │ │ ├── repository │ │ ├── ProblemRepository.java │ │ ├── ProjectRepository.java │ │ └── subProblemRepository.java │ │ ├── service │ │ ├── ProblemService.java │ │ ├── ProblemServiceImpl.java │ │ ├── ProjectService.java │ │ ├── ProjectServiceImpl.java │ │ ├── subProblemService.java │ │ └── subProblemServiceImpl.java │ │ └── swagger │ │ └── SwaggerConfig.java └── resources │ └── application.yml └── test └── java └── com └── sw └── project └── ProjectApiApplicationTests.java /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 S.M Lee 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![HitCount](http://hits.dwyl.io/phantasmicmeans/spring-boot-restful-api-example.svg)](http://hits.dwyl.io/phantasmicmeans/spring-boot-restful-api-example) 2 | 3 | # Spring Boot RESTful API - JPA Hibernate MySQL Example # 4 | *by S.M.Lee(phantasmicmeans)* 5 | 6 | RESTful API using Spring Boot, Swagger2, JPA hibernate and Mysql, One to Many, Many to One bidirectional mapping 7 | 8 |   9 | 10 | ## Relation ## 11 | 12 | ![image](https://user-images.githubusercontent.com/28649770/44622337-69c67a80-a8f1-11e8-99d7-34adb90779a3.png) 13 | 14 | 15 | ### Bidirectional Mapping ### 16 | 17 | * Project - Problem (One-To-Many) 18 | * Problem - Project (Many-To-One) 19 | 20 | * Problem - SubProblem (One-To-Many) 21 | * SubProblem - Problem (Many-To-One) 22 | 23 |   24 | 25 | ## Before we go, Check the domain class ## 26 | 27 | **1. Problem.java(part of)** 28 | 29 | ```java 30 | @OneToMany(mappedBy = "project", cascade = CascadeType.REMOVE, fetch = FetchType.LAZY, orphanRemoval = true) 31 | private Set problems = new HashSet<>(); 32 | /* Project <-> Problem One to Many bidirectional */ 33 | ``` 34 | 35 | **2. Problem.java(part of)** 36 | 37 | ```java 38 | @ManyToOne(cascade = CascadeType.REMOVE) 39 | @JoinColumn(name = "code", referencedColumnName = "code", nullable = false) 40 | private Project project; 41 | /* Problem <-> Project Many to One bidirectional */ 42 | 43 | @OneToMany(mappedBy = "problem", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true) 44 | private Set subProblems = new HashSet<>(); 45 | //Problem <-> SubProblem One to Many bidirectional 46 | ``` 47 | 48 | **3. SubProblem.java(part of)** 49 | 50 | ```java 51 | @ManyToOne(cascade = CascadeType.REMOVE) 52 | @JoinColumn(name = "pro_idx", referencedColumnName = "idx", nullable = false) 53 | private Problem problem; 54 | /* Problem <-> Project Many to One bidirectional */ 55 | ``` 56 | 57 |   58 | 59 | 60 | ## RESTful API Server ## 61 | 62 |   63 | **1. API Description for Project** 64 | 65 | METHOD | PATH | DESCRIPTION 66 | ------------|-----|------------ 67 | GET | /api/project/{code} | get Project-Problem-SubProblem with code 68 | POST | /api/project | save Project (code will generate by constructor) 69 | DELETE | /api/project/{code} | delete Project with code 70 | PUT | /api/project/{code} | update Project with code 71 | 72 |   73 | **2. API Description for Problem & SubProblem** 74 | 75 | METHOD | PATH | DESCRIPTION 76 | ------------|-----|------------ 77 | GET | /api/problem/{code} | get all Problem-Subproblem with code 78 | POST | /api/problem/{code} | save Problem with code 79 | DELETE | /api/problem/{code}/all | delete all Problem-Subproblem with code 80 | POST | /api/subproblem | save Subproblem 81 | 82 |   83 | 84 | ## Curl ## 85 | 86 |   87 | **1. Curl for Project** 88 | 89 | 1. Get a Project with code 90 | ```bash 91 | curl -X GET http://localhost:8080/problem/0gn547 92 | ``` 93 | 94 | 2. Save a Project with code 95 | ```bash 96 | curl -d '{"title":"first project"}' -H "Content-Type: application/json" -X POST http://localhost:8080/project 97 | ``` 98 | 99 | 3. Delete a Project with code 100 | ```bash 101 | curl -X DELETE http://localhost:8001/project/0gn547 102 | ``` 103 | 104 | 4. Update a Project with code 105 | ```bash 106 | curl -X PUT -H "Content-Type: application/json; charset=utf-8" -d '{"title":"first-project-renewal"}' http://localhost:8080/project/hx6029 107 | ``` 108 |   109 | 110 | **2. Curl for Problem & SubProblem** 111 |   112 | 113 | 1. Get a Problem with code 114 | ```bash 115 | curl -X GET http://localhost:8001/problem/0gn547 116 | ``` 117 | 118 | 2. Save a Problem with code 119 | ```bash 120 | curl -d '{"title":"first problem"}' -H "Content-Type: application/json" -X POST http://localhost:8080/problem/hx6029 121 | ``` 122 | 123 | 3. Delete a Problem-SubProblem with code 124 | ```bash 125 | curl -X DELETE http://localhost:8001/problem/hx6029/all 126 | ``` 127 | 4. Save a SubProblem 128 | ```bash 129 | curl -d '{"content":"first-subproblem","pro_idx":1}' -H "Content-Type: application/json" -X POST http://localhost:8080/subproblem 130 | ``` 131 |   132 | 133 | ## Running the project with MySQL ## 134 | 135 | append this at the end of application.yml 136 |   137 | 138 | ```yml 139 | spring: 140 | application: 141 | name: project-api 142 | 143 | ## Hibernate Properties 144 | # The SQL dialect makes Hibernate generate better SQL for the chosen database 145 | jpa: 146 | properties: 147 | hibernate: 148 | dialect: org.hibernate.dialect.MySQL5InnoDBDialect 149 | hibernate: 150 | ddl-auto: update 151 | # Hibernate ddl auto (create, create-drop, validate, update) 152 | 153 | datasource: 154 | url: jdbc:mysql://{YOUR_MSQL_SERVER}:3306/{DATABASE NAME}?useSSL=false 155 | username: {YOUR_MYSQL_ID} 156 | password: {YOUR_MYSQL{PASSWORD} 157 | driver-class-name: com.mysql.jdbc.Driver 158 | hikari: 159 | maximum-pool-size: 2 160 | ``` 161 | 162 |   163 | 164 | 165 | ## Swagger ## 166 | 167 | You can use the Swagger API Documentation at http://{Your_Server}:{Port}/swagger-ui.html 168 | 169 | ![image](https://user-images.githubusercontent.com/28649770/44622453-8bc0fc80-a8f3-11e8-9223-b5a21717ba6d.png) 170 | 171 | -------------------------------------------------------------------------------- /mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven2 Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /etc/mavenrc ] ; then 40 | . /etc/mavenrc 41 | fi 42 | 43 | if [ -f "$HOME/.mavenrc" ] ; then 44 | . "$HOME/.mavenrc" 45 | fi 46 | 47 | fi 48 | 49 | # OS specific support. $var _must_ be set to either true or false. 50 | cygwin=false; 51 | darwin=false; 52 | mingw=false 53 | case "`uname`" in 54 | CYGWIN*) cygwin=true ;; 55 | MINGW*) mingw=true;; 56 | Darwin*) darwin=true 57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 59 | if [ -z "$JAVA_HOME" ]; then 60 | if [ -x "/usr/libexec/java_home" ]; then 61 | export JAVA_HOME="`/usr/libexec/java_home`" 62 | else 63 | export JAVA_HOME="/Library/Java/Home" 64 | fi 65 | fi 66 | ;; 67 | esac 68 | 69 | if [ -z "$JAVA_HOME" ] ; then 70 | if [ -r /etc/gentoo-release ] ; then 71 | JAVA_HOME=`java-config --jre-home` 72 | fi 73 | fi 74 | 75 | if [ -z "$M2_HOME" ] ; then 76 | ## resolve links - $0 may be a link to maven's home 77 | PRG="$0" 78 | 79 | # need this for relative symlinks 80 | while [ -h "$PRG" ] ; do 81 | ls=`ls -ld "$PRG"` 82 | link=`expr "$ls" : '.*-> \(.*\)$'` 83 | if expr "$link" : '/.*' > /dev/null; then 84 | PRG="$link" 85 | else 86 | PRG="`dirname "$PRG"`/$link" 87 | fi 88 | done 89 | 90 | saveddir=`pwd` 91 | 92 | M2_HOME=`dirname "$PRG"`/.. 93 | 94 | # make it fully qualified 95 | M2_HOME=`cd "$M2_HOME" && pwd` 96 | 97 | cd "$saveddir" 98 | # echo Using m2 at $M2_HOME 99 | fi 100 | 101 | # For Cygwin, ensure paths are in UNIX format before anything is touched 102 | if $cygwin ; then 103 | [ -n "$M2_HOME" ] && 104 | M2_HOME=`cygpath --unix "$M2_HOME"` 105 | [ -n "$JAVA_HOME" ] && 106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 107 | [ -n "$CLASSPATH" ] && 108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 109 | fi 110 | 111 | # For Migwn, ensure paths are in UNIX format before anything is touched 112 | if $mingw ; then 113 | [ -n "$M2_HOME" ] && 114 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 115 | [ -n "$JAVA_HOME" ] && 116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 117 | # TODO classpath? 118 | fi 119 | 120 | if [ -z "$JAVA_HOME" ]; then 121 | javaExecutable="`which javac`" 122 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 123 | # readlink(1) is not available as standard on Solaris 10. 124 | readLink=`which readlink` 125 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 126 | if $darwin ; then 127 | javaHome="`dirname \"$javaExecutable\"`" 128 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 129 | else 130 | javaExecutable="`readlink -f \"$javaExecutable\"`" 131 | fi 132 | javaHome="`dirname \"$javaExecutable\"`" 133 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 134 | JAVA_HOME="$javaHome" 135 | export JAVA_HOME 136 | fi 137 | fi 138 | fi 139 | 140 | if [ -z "$JAVACMD" ] ; then 141 | if [ -n "$JAVA_HOME" ] ; then 142 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 143 | # IBM's JDK on AIX uses strange locations for the executables 144 | JAVACMD="$JAVA_HOME/jre/sh/java" 145 | else 146 | JAVACMD="$JAVA_HOME/bin/java" 147 | fi 148 | else 149 | JAVACMD="`which java`" 150 | fi 151 | fi 152 | 153 | if [ ! -x "$JAVACMD" ] ; then 154 | echo "Error: JAVA_HOME is not defined correctly." >&2 155 | echo " We cannot execute $JAVACMD" >&2 156 | exit 1 157 | fi 158 | 159 | if [ -z "$JAVA_HOME" ] ; then 160 | echo "Warning: JAVA_HOME environment variable is not set." 161 | fi 162 | 163 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 164 | 165 | # traverses directory structure from process work directory to filesystem root 166 | # first directory with .mvn subdirectory is considered project base directory 167 | find_maven_basedir() { 168 | 169 | if [ -z "$1" ] 170 | then 171 | echo "Path not specified to find_maven_basedir" 172 | return 1 173 | fi 174 | 175 | basedir="$1" 176 | wdir="$1" 177 | while [ "$wdir" != '/' ] ; do 178 | if [ -d "$wdir"/.mvn ] ; then 179 | basedir=$wdir 180 | break 181 | fi 182 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 183 | if [ -d "${wdir}" ]; then 184 | wdir=`cd "$wdir/.."; pwd` 185 | fi 186 | # end of workaround 187 | done 188 | echo "${basedir}" 189 | } 190 | 191 | # concatenates all lines of a file 192 | concat_lines() { 193 | if [ -f "$1" ]; then 194 | echo "$(tr -s '\n' ' ' < "$1")" 195 | fi 196 | } 197 | 198 | BASE_DIR=`find_maven_basedir "$(pwd)"` 199 | if [ -z "$BASE_DIR" ]; then 200 | exit 1; 201 | fi 202 | 203 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 204 | echo $MAVEN_PROJECTBASEDIR 205 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 206 | 207 | # For Cygwin, switch paths to Windows format before running java 208 | if $cygwin; then 209 | [ -n "$M2_HOME" ] && 210 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 211 | [ -n "$JAVA_HOME" ] && 212 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 213 | [ -n "$CLASSPATH" ] && 214 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 215 | [ -n "$MAVEN_PROJECTBASEDIR" ] && 216 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` 217 | fi 218 | 219 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 220 | 221 | exec "$JAVACMD" \ 222 | $MAVEN_OPTS \ 223 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 224 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 225 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 226 | -------------------------------------------------------------------------------- /mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven2 Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' 39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 40 | 41 | @REM set %HOME% to equivalent of $HOME 42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 43 | 44 | @REM Execute a user defined script before this one 45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 49 | :skipRcPre 50 | 51 | @setlocal 52 | 53 | set ERROR_CODE=0 54 | 55 | @REM To isolate internal variables from possible post scripts, we use another setlocal 56 | @setlocal 57 | 58 | @REM ==== START VALIDATION ==== 59 | if not "%JAVA_HOME%" == "" goto OkJHome 60 | 61 | echo. 62 | echo Error: JAVA_HOME not found in your environment. >&2 63 | echo Please set the JAVA_HOME variable in your environment to match the >&2 64 | echo location of your Java installation. >&2 65 | echo. 66 | goto error 67 | 68 | :OkJHome 69 | if exist "%JAVA_HOME%\bin\java.exe" goto init 70 | 71 | echo. 72 | echo Error: JAVA_HOME is set to an invalid directory. >&2 73 | echo JAVA_HOME = "%JAVA_HOME%" >&2 74 | echo Please set the JAVA_HOME variable in your environment to match the >&2 75 | echo location of your Java installation. >&2 76 | echo. 77 | goto error 78 | 79 | @REM ==== END VALIDATION ==== 80 | 81 | :init 82 | 83 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 84 | @REM Fallback to current working directory if not found. 85 | 86 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 87 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 88 | 89 | set EXEC_DIR=%CD% 90 | set WDIR=%EXEC_DIR% 91 | :findBaseDir 92 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 93 | cd .. 94 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 95 | set WDIR=%CD% 96 | goto findBaseDir 97 | 98 | :baseDirFound 99 | set MAVEN_PROJECTBASEDIR=%WDIR% 100 | cd "%EXEC_DIR%" 101 | goto endDetectBaseDir 102 | 103 | :baseDirNotFound 104 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 105 | cd "%EXEC_DIR%" 106 | 107 | :endDetectBaseDir 108 | 109 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 110 | 111 | @setlocal EnableExtensions EnableDelayedExpansion 112 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 113 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 114 | 115 | :endReadAdditionalConfig 116 | 117 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 118 | 119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 121 | 122 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 123 | if ERRORLEVEL 1 goto error 124 | goto end 125 | 126 | :error 127 | set ERROR_CODE=1 128 | 129 | :end 130 | @endlocal & set ERROR_CODE=%ERROR_CODE% 131 | 132 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 133 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 134 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 135 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 136 | :skipRcPost 137 | 138 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 139 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 140 | 141 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 142 | 143 | exit /B %ERROR_CODE% 144 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.example 7 | project-api 8 | 0.0.1 9 | jar 10 | 11 | project-api 12 | project-api 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 3.0.4 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 17 25 | 26 | 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter-web 31 | 32 | 33 | org.springframework.boot 34 | spring-boot-starter-validation 35 | 36 | 37 | com.google.code.gson 38 | gson 39 | 2.8.5 40 | 41 | 42 | org.springdoc 43 | springdoc-openapi-starter-webmvc-ui 44 | 2.0.2 45 | 46 | 47 | org.springframework.boot 48 | spring-boot-starter-data-jpa 49 | 50 | 51 | com.mysql 52 | mysql-connector-j 53 | 54 | 55 | org.springframework 56 | spring-orm 57 | 58 | 59 | org.springframework.boot 60 | spring-boot-starter-test 61 | test 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | org.springframework.boot 70 | spring-boot-maven-plugin 71 | 72 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /src/main/java/com/sw/project/ProjectApiApplication.java: -------------------------------------------------------------------------------- 1 | package com.sw.project; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class ProjectApiApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(ProjectApiApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/sw/project/aspect/RestControllerAspect.java: -------------------------------------------------------------------------------- 1 | package com.sw.project.aspect; 2 | 3 | 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | //@Aspect 8 | //@Component 9 | public class RestControllerAspect { 10 | 11 | protected final Logger log = LoggerFactory.getLogger(this.getClass()); 12 | 13 | // @Pointcut("execution(* com.sw.project.controller.*(..)") 14 | // private void pointCutBeforeApi() { 15 | // } 16 | 17 | //@Before("pointCutBeforeApi()") 18 | // public void loggerBeforeRestCall(JoinPoint joinPoint) throws Throwable{ 19 | // 20 | // log.info("======== AOP Before RestAPI Call ==========" + joinPoint); 21 | // } 22 | // 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/sw/project/config/JpaConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.sw.project.config; 2 | 3 | import org.springframework.context.annotation.Configuration; 4 | import org.springframework.data.jpa.repository.config.EnableJpaAuditing; 5 | 6 | /* 7 | * JPA Config 8 | */ 9 | @EnableJpaAuditing 10 | @Configuration 11 | public class JpaConfiguration { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/sw/project/controller/ProblemController.java: -------------------------------------------------------------------------------- 1 | package com.sw.project.controller; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.JsonObject; 5 | import com.sw.project.domain.Problem; 6 | import com.sw.project.domain.Project; 7 | import com.sw.project.exception.DataFormatException; 8 | import com.sw.project.exception.ElementNullException; 9 | import com.sw.project.exception.ResourceNotFoundException; 10 | import com.sw.project.repository.ProblemRepository; 11 | import com.sw.project.service.ProblemService; 12 | import com.sw.project.service.ProjectService; 13 | import io.swagger.v3.oas.annotations.Operation; 14 | import jakarta.validation.Valid; 15 | import org.slf4j.Logger; 16 | import org.slf4j.LoggerFactory; 17 | import org.springframework.beans.factory.annotation.Autowired; 18 | import org.springframework.http.HttpStatus; 19 | import org.springframework.http.ResponseEntity; 20 | import org.springframework.web.bind.annotation.PathVariable; 21 | import org.springframework.web.bind.annotation.RequestBody; 22 | import org.springframework.web.bind.annotation.RequestMapping; 23 | import org.springframework.web.bind.annotation.RequestMethod; 24 | import org.springframework.web.bind.annotation.RestController; 25 | import org.springframework.web.servlet.support.ServletUriComponentsBuilder; 26 | 27 | import java.net.URI; 28 | import java.util.Collection; 29 | 30 | @RestController 31 | @RequestMapping(value = "api/problem") 32 | public class ProblemController { 33 | 34 | @Autowired 35 | ProjectService projectService; 36 | 37 | @Autowired 38 | ProblemService problemService; 39 | 40 | @Autowired 41 | ProblemRepository problemRepository; 42 | 43 | private final Logger logger = LoggerFactory.getLogger(this.getClass()); 44 | 45 | @RequestMapping(value = "/{code}", method = RequestMethod.GET, 46 | produces = {"application/json"}) 47 | @Operation(summary = "code로 문제 조회", description = "code는 6자리 영문과 숫자조합") 48 | public ResponseEntity> getProblemByCode(@Valid @PathVariable("code") final String code){ 49 | 50 | if(code.length() < 6 || code.equals("")) 51 | throw new DataFormatException("Please check your code"); 52 | 53 | Collection problemCollection = problemRepository.findByProblemWithCode((code)); 54 | 55 | if(problemCollection.isEmpty()) 56 | throw new ElementNullException("No data with this code"); 57 | 58 | return new ResponseEntity> (problemCollection, HttpStatus.OK); 59 | 60 | } 61 | 62 | 63 | @RequestMapping(value = "{code}", method = RequestMethod.POST 64 | , consumes = "application/json") 65 | @Operation(summary = "문제 생성", description = "code는 6자리 영문과 숫자조합, problem parameter는 사용 X") 66 | public ResponseEntity saveProblem(@Valid @RequestBody Problem problem, 67 | @PathVariable("code")final String code){ 68 | 69 | if(code.length() < 6 || code.equals("")) { 70 | logger.info("dfsdfsdfsdfsdf"); 71 | throw new DataFormatException("Please check your code"); 72 | } 73 | Project project = projectService.findProjectByCode(code) 74 | .orElseThrow(() -> new ResourceNotFoundException("No Project with that Code")); 75 | 76 | problem.setProject(project); 77 | 78 | if(problemService.saveProblem(problem)) { 79 | 80 | project.addProblem(problem); 81 | URI location = ServletUriComponentsBuilder.fromCurrentRequest().buildAndExpand(problem.getTitle()).toUri(); 82 | 83 | return ResponseEntity.created(location).build(); 84 | } 85 | 86 | String result = "Data Not Valid, Please Check Yout title"; 87 | return new ResponseEntity (getJson(result), HttpStatus.BAD_REQUEST); 88 | } 89 | 90 | @RequestMapping(value = "/{code}", method = RequestMethod.DELETE) 91 | @Operation(summary = "code로 최근 문제 삭제", description = "code는 6자리 영문과 숫자조합") 92 | public ResponseEntity deleteProblem(@Valid @PathVariable("code") final String code) { 93 | //code가 "code"인 데이터들을 찾아와서 94 | 95 | if (code.length() < 6 || code.equals("")) 96 | throw new DataFormatException("Please check your code"); 97 | 98 | // problemService.deleteProblem(code); 99 | problemService.deleteAllProblemWithCode(code); 100 | 101 | return new ResponseEntity(HttpStatus.OK); 102 | } 103 | 104 | @RequestMapping(value = "/{code}/all", method = RequestMethod.DELETE) 105 | @Operation(summary = "code로 모든 문제 삭제, ", description = "code는 6자리 영문과 숫자조합") 106 | public ResponseEntity deleteAllProblem(@Valid @PathVariable("code") final String code){ 107 | 108 | if(code.length() < 6 || code.equals("")) 109 | throw new DataFormatException("Please check your code"); 110 | 111 | if(!problemService.deleteAllProblemAndSubWithCode(code)) 112 | throw new ResourceNotFoundException("No Problem with that code"); 113 | 114 | return new ResponseEntity(HttpStatus.OK); 115 | } 116 | 117 | static String getJson(String result) { 118 | 119 | JsonObject object = new JsonObject(); 120 | object.addProperty("result", result); 121 | return new Gson().toJson(object); 122 | } 123 | 124 | 125 | } 126 | -------------------------------------------------------------------------------- /src/main/java/com/sw/project/controller/ProjectController.java: -------------------------------------------------------------------------------- 1 | package com.sw.project.controller; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.JsonObject; 5 | import com.sw.project.domain.Project; 6 | import com.sw.project.exception.DataFormatException; 7 | import com.sw.project.exception.ResourceNotFoundException; 8 | import com.sw.project.repository.ProblemRepository; 9 | import com.sw.project.service.ProjectService; 10 | import io.swagger.v3.oas.annotations.Operation; 11 | import jakarta.validation.Valid; 12 | import org.slf4j.Logger; 13 | import org.slf4j.LoggerFactory; 14 | import org.springframework.beans.factory.annotation.Autowired; 15 | import org.springframework.http.HttpStatus; 16 | import org.springframework.http.ResponseEntity; 17 | import org.springframework.web.bind.annotation.CrossOrigin; 18 | import org.springframework.web.bind.annotation.PathVariable; 19 | import org.springframework.web.bind.annotation.RequestBody; 20 | import org.springframework.web.bind.annotation.RequestMapping; 21 | import org.springframework.web.bind.annotation.RequestMethod; 22 | import org.springframework.web.bind.annotation.RestController; 23 | import org.springframework.web.servlet.support.ServletUriComponentsBuilder; 24 | 25 | import java.net.URI; 26 | 27 | @CrossOrigin(origins = "*") 28 | @RequestMapping(value = "api/project") 29 | @RestController 30 | public class ProjectController { 31 | 32 | @Autowired 33 | private ProjectService projectService; 34 | 35 | 36 | private final Logger logger = LoggerFactory.getLogger(this.getClass()); 37 | 38 | @Autowired 39 | private ProblemRepository problemRepository; 40 | 41 | @RequestMapping(value = "/{code}", method = RequestMethod.GET, 42 | produces = {"application/json", "application/xml"}) 43 | @Operation(summary = "code로 프로젝트 조회", description = "code는 6자리 영문과 숫자조합 ") 44 | public ResponseEntity getProject(@Valid @PathVariable("code") final String code) { //code로 프로젝트 찾음(code unique). 45 | 46 | 47 | if (code.length() < 6 || code.equals("")) 48 | throw new DataFormatException("Please Check your code"); 49 | 50 | Project project = projectService.findProjectByCode(code) 51 | .orElseThrow(() -> new ResourceNotFoundException("No Project with that code")); 52 | //find project -> 404 53 | 54 | return new ResponseEntity(project, HttpStatus.OK); 55 | 56 | } 57 | 58 | @RequestMapping(value = "", method = RequestMethod.POST, 59 | consumes = {"application/json"}, 60 | produces = {"application/json"}) 61 | @Operation(summary = "프로젝트 생성", description = "code는 자동생성, title(String) 필요") 62 | public ResponseEntity createProject(@Valid @RequestBody Project project) { 63 | 64 | String title = project.getTitle(); 65 | 66 | if(title.length() < 5) 67 | throw new DataFormatException("Title must be more than length 5"); 68 | 69 | project = new Project(title); 70 | 71 | String result = projectService.saveProject(project); 72 | 73 | if(result.equals("1")) { //title만 받고, code는 생성자가 랜덤으로 생성. 74 | 75 | URI location = ServletUriComponentsBuilder.fromCurrentRequest().buildAndExpand(project.getTitle()).toUri(); 76 | return ResponseEntity.created(location).build(); 77 | } 78 | 79 | return new ResponseEntity (getJson(result), HttpStatus.BAD_REQUEST); 80 | 81 | } 82 | 83 | @RequestMapping(value = "/{code}", method = RequestMethod.DELETE) 84 | @Operation(summary = "code로 프로젝트 삭제", description = "code 필요") 85 | ResponseEntity deleteProject(@Valid @PathVariable("code") final String code){ 86 | 87 | if(code.length() < 6 || code.equals("")) 88 | throw new DataFormatException("Please Check your code"); 89 | 90 | if(!projectService.deleteProject(code)) { 91 | return new ResponseEntity<>(HttpStatus.NOT_FOUND); 92 | } 93 | 94 | return new ResponseEntity<>(HttpStatus.OK); //project delete 95 | 96 | } 97 | 98 | @RequestMapping(value = "/{code}", method = RequestMethod.PUT, 99 | consumes = {"application/json"}, 100 | produces = {"application/json"}) 101 | @Operation(summary = "project 업데이트", description = "code로 project 변경, title 필요") 102 | public ResponseEntity updateProject(@Valid @PathVariable("code") final String code, @RequestBody Project project) 103 | { 104 | if(code.length() < 6 || code.equals("")) 105 | throw new DataFormatException("Please Check your code"); 106 | 107 | Project pjt = projectService.findProjectByCode(code) 108 | .orElseThrow(() -> new ResourceNotFoundException("No Project with that code")); 109 | 110 | pjt.setTitle(project.getTitle()); 111 | 112 | if(!projectService.updateProject(pjt)) 113 | return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); 114 | 115 | return new ResponseEntity<>(HttpStatus.OK); 116 | 117 | } 118 | 119 | static String getJson(String ipt) { /*String to Json Converter*/ 120 | 121 | JsonObject object = new JsonObject(); 122 | object.addProperty("result", ipt); 123 | return new Gson().toJson(object); 124 | } 125 | 126 | 127 | } 128 | -------------------------------------------------------------------------------- /src/main/java/com/sw/project/controller/subProblemController.java: -------------------------------------------------------------------------------- 1 | package com.sw.project.controller; 2 | 3 | import com.sw.project.domain.Problem; 4 | import com.sw.project.domain.subProblem; 5 | import com.sw.project.domain.subProblemBody; 6 | import com.sw.project.exception.DataFormatException; 7 | import com.sw.project.exception.ResourceNotFoundException; 8 | import com.sw.project.service.ProblemService; 9 | import com.sw.project.service.subProblemService; 10 | import jakarta.validation.Valid; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.http.HttpStatus; 13 | import org.springframework.http.ResponseEntity; 14 | import org.springframework.web.bind.annotation.RequestBody; 15 | import org.springframework.web.bind.annotation.RequestMapping; 16 | import org.springframework.web.bind.annotation.RequestMethod; 17 | import org.springframework.web.bind.annotation.RestController; 18 | import org.springframework.web.servlet.support.ServletUriComponentsBuilder; 19 | 20 | import java.net.URI; 21 | 22 | @RestController 23 | @RequestMapping(value = "api/subproblem") 24 | public class subProblemController { 25 | @Autowired 26 | subProblemService subproblemService; 27 | 28 | @Autowired 29 | ProblemService problemService; 30 | 31 | 32 | @RequestMapping(value="", method = RequestMethod.POST, 33 | produces = {"application/json"}) 34 | public ResponseEntity saveSubProblem(@Valid @RequestBody subProblemBody problemBody/*subProblem subproblem*/){ 35 | 36 | 37 | if(problemBody.getContent().length() < 10 || problemBody.getContent().equals("")) { 38 | throw new DataFormatException("Please check your content, content must be more than 10 length"); 39 | } //content length check 40 | 41 | 42 | Problem problem = problemService.getProblemById(problemBody.getPro_idx()) // problem search with idx 43 | .orElseThrow(()-> new ResourceNotFoundException("Cannot found problem with that idx")); 44 | 45 | subProblem subproblem = new subProblem(problemBody.getContent(), problem); 46 | 47 | if(subproblemService.saveSubProblem(subproblem)) { //save 48 | problem.addSubProblem(subproblem); 49 | URI location = ServletUriComponentsBuilder.fromCurrentRequest().buildAndExpand(subproblem.getIdx()).toUri(); 50 | return ResponseEntity.created(location).build(); 51 | } 52 | 53 | return new ResponseEntity (HttpStatus.INTERNAL_SERVER_ERROR); 54 | } 55 | 56 | /*@RequestMapping(value="/{idx}/all", method = RequestMethod.GET, 57 | produces = {"application/json"}) 58 | public ResponseEntity getSubProblem(@Valid @PathVariable final String idx){ 59 | 60 | if(idx == null) throw new DataFormatException("Please check your content, content must have idx"); 61 | 62 | 63 | }*/ 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/com/sw/project/domain/AuditModel.java: -------------------------------------------------------------------------------- 1 | package com.sw.project.domain; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import jakarta.persistence.Column; 5 | import jakarta.persistence.EntityListeners; 6 | import jakarta.persistence.MappedSuperclass; 7 | import org.springframework.data.annotation.CreatedDate; 8 | import org.springframework.data.annotation.LastModifiedDate; 9 | import org.springframework.data.jpa.domain.support.AuditingEntityListener; 10 | 11 | import java.io.Serializable; 12 | import java.sql.Date; 13 | 14 | @MappedSuperclass 15 | @EntityListeners(AuditingEntityListener.class) //생성시간, 수정시간, 생성자, 수정자 등이 구현된 class 16 | @JsonIgnoreProperties( 17 | value = {"createdAt", "updatedAt"}, //그중 createdAt, updatedAt은 우리가 따로 쓸것임. 18 | allowGetters = true 19 | ) 20 | public abstract class AuditModel implements Serializable { 21 | 22 | 23 | private static final long serialVersionUID = 1L; 24 | 25 | @Column(name = "created_at", nullable = false, updatable = false) 26 | @CreatedDate 27 | private Date createdAt; 28 | 29 | @Column(name = "updated_at", nullable = false) 30 | @LastModifiedDate 31 | private Date updatedAt; 32 | 33 | public Date getCreatedAt() { 34 | return createdAt; 35 | } 36 | 37 | public void setCreatedAt(Date createdAt) { 38 | this.createdAt = createdAt; 39 | } 40 | 41 | public Date getUpdatedAt() { 42 | return updatedAt; 43 | } 44 | 45 | public void setUpdatedAt(Date updatedAt) { 46 | this.updatedAt = updatedAt; 47 | } 48 | 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/sw/project/domain/LocalDateAttributeConverter.java: -------------------------------------------------------------------------------- 1 | package com.sw.project.domain; 2 | 3 | import jakarta.persistence.AttributeConverter; 4 | 5 | import java.sql.Date; 6 | import java.time.LocalDate; 7 | 8 | 9 | public class LocalDateAttributeConverter implements AttributeConverter { 10 | 11 | @Override 12 | public Date convertToDatabaseColumn(LocalDate locDate) { 13 | return (locDate == null ? null : Date.valueOf(locDate)); 14 | } 15 | 16 | @Override 17 | public LocalDate convertToEntityAttribute(Date sqlDate) { 18 | return (sqlDate == null ? null : sqlDate.toLocalDate()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/sw/project/domain/LocalDateTimeAttributeConverter.java: -------------------------------------------------------------------------------- 1 | package com.sw.project.domain; 2 | 3 | import jakarta.persistence.AttributeConverter; 4 | 5 | import java.sql.Timestamp; 6 | import java.time.LocalDateTime; 7 | 8 | 9 | public class LocalDateTimeAttributeConverter implements AttributeConverter { 10 | 11 | @Override 12 | public Timestamp convertToDatabaseColumn(LocalDateTime locDateTime) { 13 | return (locDateTime == null ? null : Timestamp.valueOf(locDateTime)); 14 | } 15 | 16 | @Override 17 | public LocalDateTime convertToEntityAttribute(Timestamp sqlTimestamp) { 18 | return (sqlTimestamp == null ? null : sqlTimestamp.toLocalDateTime()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/sw/project/domain/Problem.java: -------------------------------------------------------------------------------- 1 | package com.sw.project.domain; 2 | 3 | import jakarta.persistence.*; 4 | 5 | import java.io.Serializable; 6 | import java.util.HashSet; 7 | import java.util.Set; 8 | 9 | 10 | @Entity 11 | @Table(name = "Problem") 12 | public class Problem implements Serializable{ 13 | 14 | 15 | private static final long serialVersionUID = 1L; 16 | 17 | @Id 18 | @Column(name = "idx") 19 | @GeneratedValue(strategy = GenerationType.IDENTITY) 20 | private Long idx; 21 | 22 | @Column(name = "title") 23 | private String title; 24 | 25 | @ManyToOne(cascade = CascadeType.REMOVE) 26 | @JoinColumn(name = "code", referencedColumnName = "code", nullable = false) 27 | private Project project; //Problem <-> Project Many to one 28 | 29 | @OneToMany(mappedBy = "problem", cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true) 30 | private final Set subProblems = new HashSet<>(); 31 | 32 | 33 | public Problem() { }//JPA constructor 34 | 35 | public Problem(String title, final Project project) { 36 | 37 | this.project = project; 38 | this.title = title; 39 | } 40 | 41 | public Long getIdx() { 42 | return idx; 43 | } 44 | 45 | public String getTitle() { 46 | return title; 47 | } 48 | 49 | public void setTitle(String title) { 50 | this.title = title; 51 | } 52 | 53 | public String getProblemCode() { 54 | return this.project.getCode(); 55 | } 56 | 57 | public void setProject(Project project) { 58 | this.project = project; 59 | } 60 | 61 | public void addSubProblem(subProblem subproblem) { 62 | this.subProblems.add(subproblem); 63 | } 64 | 65 | @Override 66 | public String toString() { 67 | // TODO Auto-generated method stub 68 | return "idx : "+ idx + " title : "+ title + "code : "+ project.getCode(); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/com/sw/project/domain/Project.java: -------------------------------------------------------------------------------- 1 | package com.sw.project.domain; 2 | 3 | import jakarta.persistence.*; 4 | import jakarta.validation.constraints.NotNull; 5 | import jakarta.validation.constraints.Size; 6 | 7 | import java.io.Serializable; 8 | import java.util.HashSet; 9 | import java.util.Random; 10 | import java.util.Set; 11 | 12 | 13 | 14 | @Entity 15 | @Table(name = "Project") 16 | public class Project implements Serializable { 17 | 18 | private static final long serialVersionUID = 1L; 19 | 20 | @Id 21 | @Column(name = "idx") 22 | @GeneratedValue(strategy = GenerationType.IDENTITY) 23 | private Long idx; 24 | 25 | @Size(max=6) 26 | @Column(name = "code", unique=true, nullable=false) 27 | private String code; 28 | 29 | @NotNull 30 | @Size(max = 200) 31 | @Column(name = "title",nullable=false) 32 | private String title; 33 | 34 | @OneToMany(mappedBy = "project", cascade = CascadeType.REMOVE, fetch = FetchType.LAZY, orphanRemoval = true) 35 | private final Set problems = new HashSet<>(); //Project <-> Problems OneToMany 36 | 37 | public Project() { 38 | } 39 | 40 | public Project(final String title) { 41 | 42 | this.code = firstCode(); 43 | this.title = title; 44 | // TODO Auto-generated constructor stub 45 | } 46 | 47 | public Long getIdx() { 48 | return idx; 49 | } 50 | 51 | public String getTitle() { 52 | return title; 53 | } 54 | public void setTitle(String title) { 55 | this.title = title; 56 | } 57 | 58 | public String getCode() { 59 | return code; 60 | } 61 | 62 | public void setCode() { 63 | 64 | this.code = randomCode(); 65 | } 66 | 67 | public void addProblem(Problem problem) { 68 | problems.add(problem); 69 | } 70 | 71 | public Set getProblem() { 72 | return problems; 73 | } 74 | 75 | @Override 76 | public String toString() { 77 | // TODO Auto-generated method stub 78 | return "idx : " + idx + " title : " + title + " code :" + code; 79 | 80 | } 81 | 82 | public String firstCode() { 83 | 84 | return randomCode(); 85 | } 86 | 87 | public String randomCode() { //6자리 인증 88 | 89 | Random rnd = new Random(); 90 | StringBuffer buf = new StringBuffer(); 91 | for(int i=0;i<6;i++){ 92 | if(rnd.nextBoolean()) 93 | buf.append((char)(rnd.nextInt(26) +97)); 94 | else 95 | buf.append((rnd.nextInt(10))); 96 | } 97 | return buf.toString(); 98 | } 99 | 100 | /* 101 | @Temporal(TemporalType.TIMESTAMP) 102 | @Column(name="create_time", nullable = false, updatable = false) 103 | @CreatedDate 104 | private Date createdAt; 105 | 106 | @Temporal(TemporalType.TIMESTAMP) 107 | @Column(name="last_update_time", nullable = false) 108 | @LastModifiedDate 109 | private Date last_update_time; 110 | */ 111 | 112 | } 113 | -------------------------------------------------------------------------------- /src/main/java/com/sw/project/domain/subProblem.java: -------------------------------------------------------------------------------- 1 | package com.sw.project.domain; 2 | 3 | import jakarta.persistence.*; 4 | import jakarta.validation.constraints.NotNull; 5 | import jakarta.validation.constraints.Size; 6 | 7 | import java.io.Serializable; 8 | 9 | 10 | @Entity 11 | @Table(name="subproblem") 12 | public class subProblem implements Serializable{ 13 | 14 | /** 15 | * 16 | */ 17 | private static final long serialVersionUID = 1L; 18 | 19 | @Id 20 | @Column(name="idx") 21 | @GeneratedValue(strategy = GenerationType.IDENTITY) 22 | private Long idx; 23 | 24 | //@ManyToOne(fetch = FetchType.LAZY, optional=false) 25 | @ManyToOne(cascade = CascadeType.REMOVE) 26 | @JoinColumn(name = "pro_idx", referencedColumnName = "idx", nullable = false) 27 | private Problem problem; //Problem <-> Project ManyToOne bidirectional 28 | 29 | @NotNull 30 | @Size(max=200) 31 | @Column(name="content", nullable = false) 32 | private String content; 33 | 34 | @Column(name="count") 35 | private long count=0; 36 | 37 | public subProblem() {} 38 | 39 | public subProblem(String content, Problem problem) { 40 | 41 | this.problem = problem; 42 | this.content = content; 43 | } 44 | 45 | public Long getIdx() { 46 | return idx; 47 | } 48 | 49 | public String getContent() { 50 | return content; 51 | } 52 | 53 | public void setContent(String content) { 54 | this.content = content; 55 | } 56 | 57 | public long getCount() { 58 | return count; 59 | } 60 | 61 | public void setCount(long count) { 62 | this.count = count; 63 | } 64 | 65 | 66 | 67 | } 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /src/main/java/com/sw/project/domain/subProblemBody.java: -------------------------------------------------------------------------------- 1 | package com.sw.project.domain; 2 | 3 | 4 | public class subProblemBody { 5 | 6 | private Long pro_idx; 7 | private String content; 8 | 9 | public subProblemBody() { 10 | // TODO Auto-generated constructor stub 11 | } 12 | public subProblemBody(Long pro_idx, String content) { 13 | this.pro_idx = pro_idx; 14 | this.content = content; 15 | } 16 | public Long getPro_idx() { 17 | return pro_idx; 18 | } 19 | public void setPro_idx(Long pro_idx) { 20 | this.pro_idx = pro_idx; 21 | } 22 | public String getContent() { 23 | return content; 24 | } 25 | public void setContent(String content) { 26 | this.content = content; 27 | } 28 | 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/sw/project/exception/CustmizeExceptionHandler.java: -------------------------------------------------------------------------------- 1 | package com.sw.project.exception; 2 | 3 | import java.util.Date; 4 | 5 | import org.springframework.http.HttpStatus; 6 | import org.springframework.http.ResponseEntity; 7 | import org.springframework.web.bind.annotation.ControllerAdvice; 8 | import org.springframework.web.bind.annotation.ExceptionHandler; 9 | import org.springframework.web.bind.annotation.RestController; 10 | import org.springframework.web.context.request.WebRequest; 11 | import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; 12 | 13 | @ControllerAdvice 14 | @RestController 15 | public class CustmizeExceptionHandler extends ResponseEntityExceptionHandler{ 16 | 17 | 18 | @ExceptionHandler(NotDefineException.class) 19 | public ResponseEntity Exception(NotDefineException re, WebRequest rq){ 20 | 21 | CustomizeErrorDetail errDetail = new CustomizeErrorDetail(new Date(), re.getMessage(), rq.getDescription(false)); 22 | 23 | return new ResponseEntity (errDetail, HttpStatus.NOT_FOUND); 24 | } 25 | 26 | @ExceptionHandler(ResourceNotFoundException.class) 27 | public ResponseEntity handleResourceNotFoundException(ResourceNotFoundException re, WebRequest rq){ 28 | 29 | CustomizeErrorDetail errDetail = new CustomizeErrorDetail(new Date(), re.getMessage(), rq.getDescription(false)); 30 | 31 | return new ResponseEntity (errDetail, HttpStatus.NOT_FOUND); 32 | } 33 | 34 | @ExceptionHandler(ElementNullException.class) 35 | public ResponseEntity handleElementNullException(ElementNullException re, WebRequest rq){ 36 | 37 | CustomizeErrorDetail elementErrDetail = new CustomizeErrorDetail(new Date(), re.getMessage(), rq.getDescription(false)); 38 | 39 | return new ResponseEntity (elementErrDetail, HttpStatus.NOT_IMPLEMENTED); 40 | } 41 | 42 | @ExceptionHandler(DataFormatException.class) 43 | public ResponseEntity handlDataFormatException(DataFormatException re, WebRequest rq){ 44 | 45 | CustomizeErrorDetail dataFormatErrDetail = new CustomizeErrorDetail(new Date(), re.getMessage(), rq.getDescription(false)); 46 | 47 | return new ResponseEntity (dataFormatErrDetail, HttpStatus.BAD_REQUEST); 48 | } 49 | } 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /src/main/java/com/sw/project/exception/CustomizeErrorDetail.java: -------------------------------------------------------------------------------- 1 | package com.sw.project.exception; 2 | 3 | import java.util.Date; 4 | 5 | public class CustomizeErrorDetail { 6 | 7 | private Date timeStamp; 8 | private String message; 9 | private String details; 10 | 11 | public CustomizeErrorDetail(Date timeStamp, String message, String details) { 12 | // TODO Auto-generated constructor stub 13 | this.timeStamp = timeStamp; 14 | this.message = message; 15 | this.details = details; 16 | } 17 | 18 | public Date getTimeStamp() { 19 | return timeStamp; 20 | } 21 | 22 | public String getMessage() { 23 | return message; 24 | } 25 | 26 | public String getDetails() { 27 | return details; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/sw/project/exception/DataFormatException.java: -------------------------------------------------------------------------------- 1 | package com.sw.project.exception; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.ResponseStatus; 5 | 6 | @ResponseStatus(HttpStatus.BAD_REQUEST) 7 | public final class DataFormatException extends RuntimeException{ 8 | 9 | private static final long serialVersionUID = 1L; 10 | 11 | public DataFormatException() { 12 | super(); 13 | } 14 | 15 | public DataFormatException(String message){ 16 | 17 | super(message); 18 | } 19 | 20 | public DataFormatException(String message, Throwable cause){ 21 | 22 | super(message, cause); 23 | } 24 | 25 | public DataFormatException(Throwable cause) { 26 | 27 | super(cause); 28 | } 29 | 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/sw/project/exception/ElementNullException.java: -------------------------------------------------------------------------------- 1 | package com.sw.project.exception; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.ResponseStatus; 5 | 6 | @ResponseStatus(HttpStatus.NOT_IMPLEMENTED) 7 | public class ElementNullException extends RuntimeException{ 8 | //request는 제대로 요청 됬으나, 데이터 없음. 데이터 없는경우는 404 하지 말자. 9 | private static final long serialVersionUID = 1L; 10 | 11 | public ElementNullException() { 12 | super(); 13 | } 14 | 15 | public ElementNullException(String message){ 16 | 17 | super(message); 18 | } 19 | 20 | public ElementNullException(String message, Throwable cause){ 21 | 22 | super(message, cause); 23 | } 24 | 25 | public ElementNullException(Throwable cause) { 26 | 27 | super(cause); 28 | } 29 | 30 | 31 | } 32 | 33 | -------------------------------------------------------------------------------- /src/main/java/com/sw/project/exception/InternerServerError.java: -------------------------------------------------------------------------------- 1 | package com.sw.project.exception; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.ResponseStatus; 5 | 6 | @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) 7 | public class InternerServerError extends RuntimeException{ 8 | //request는 제대로 요청 됬으나, 데이터 없음. 데이터 없는경우는 404 하지 말자. 9 | private static final long serialVersionUID = 1L; 10 | 11 | public InternerServerError() { 12 | // TODO Auto-generated constructor stub 13 | super(); 14 | } 15 | 16 | public InternerServerError(String message){ 17 | 18 | super(message); 19 | } 20 | 21 | public InternerServerError(String message, Throwable cause){ 22 | 23 | super(message, cause); 24 | } 25 | 26 | public InternerServerError(Throwable cause) { 27 | 28 | super(cause); 29 | } 30 | 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/sw/project/exception/NotDefineException.java: -------------------------------------------------------------------------------- 1 | package com.sw.project.exception; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.ResponseStatus; 5 | 6 | @ResponseStatus(HttpStatus.NOT_FOUND) 7 | public class NotDefineException extends RuntimeException { 8 | 9 | private static final long serialVersionUID = 1L; 10 | 11 | public NotDefineException() { 12 | super(); 13 | } 14 | 15 | public NotDefineException(String message) { 16 | 17 | super(message); 18 | } 19 | 20 | } 21 | 22 | -------------------------------------------------------------------------------- /src/main/java/com/sw/project/exception/NullPointerException.java: -------------------------------------------------------------------------------- 1 | package com.sw.project.exception; 2 | 3 | 4 | public class NullPointerException extends RuntimeException { 5 | 6 | private static final long serialVersionUID = 1L; 7 | 8 | public NullPointerException() { 9 | super(); 10 | } 11 | 12 | public NullPointerException(String message) { 13 | 14 | super(message); 15 | } 16 | 17 | public NullPointerException(String message, Throwable cause) { 18 | 19 | super(message,cause); 20 | } 21 | 22 | 23 | public NullPointerException(Throwable cause) { 24 | 25 | super(cause); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/sw/project/exception/ResourceNotFoundException.java: -------------------------------------------------------------------------------- 1 | package com.sw.project.exception; 2 | 3 | import org.springframework.http.HttpStatus; 4 | import org.springframework.web.bind.annotation.ResponseStatus; 5 | 6 | @ResponseStatus(HttpStatus.NOT_FOUND) 7 | public final class ResourceNotFoundException extends RuntimeException{ 8 | //data invalid 9 | private static final long serialVersionUID = 1L; 10 | 11 | public ResourceNotFoundException() { 12 | 13 | super(); //Runtime Exception super class 14 | } 15 | 16 | public ResourceNotFoundException(String message){ 17 | super(message); 18 | } 19 | 20 | public ResourceNotFoundException(String message, Throwable cause) { 21 | super(message, cause); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/sw/project/repository/ProblemRepository.java: -------------------------------------------------------------------------------- 1 | package com.sw.project.repository; 2 | 3 | import com.sw.project.domain.Problem; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.data.jpa.repository.Modifying; 6 | import org.springframework.data.jpa.repository.Query; 7 | import org.springframework.data.repository.query.Param; 8 | import org.springframework.stereotype.Repository; 9 | import org.springframework.transaction.annotation.Transactional; 10 | 11 | import java.util.Collection; 12 | 13 | @Repository 14 | public interface ProblemRepository extends JpaRepository{ 15 | 16 | @Query(value = "SELECT * FROM problem WHERE code=?1", nativeQuery = true) 17 | Collection findByProblemWithCode(@Param("code") String code); 18 | 19 | @Query(value = "SELECT * FROM problem WHERE idx=?1", nativeQuery = true) 20 | Problem getProblem(Long idx); 21 | 22 | Problem findByIdx(Long idx); 23 | 24 | @Modifying 25 | @Transactional 26 | @Query(value = "DELETE FROM problem WHERE code=?1", nativeQuery = true) 27 | void deleteAllProblemByCodeInQuery(@Param("code") String code); 28 | 29 | @Modifying 30 | @Transactional 31 | @Query(value = "DELETE FROM subproblem WHERE pro_idx = (SELECT idx FROM problem WHERE code=?1)", nativeQuery = true) 32 | void deleteAllSubProblemByCodeInQuery(@Param("code") String code); 33 | 34 | } 35 | 36 | -------------------------------------------------------------------------------- /src/main/java/com/sw/project/repository/ProjectRepository.java: -------------------------------------------------------------------------------- 1 | package com.sw.project.repository; 2 | 3 | 4 | import com.sw.project.domain.Project; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | import org.springframework.data.jpa.repository.Query; 7 | import org.springframework.stereotype.Repository; 8 | import org.springframework.transaction.annotation.Transactional; 9 | 10 | @Repository 11 | public interface ProjectRepository extends JpaRepository { 12 | 13 | @Query(value = "SELECT * FROM project WHERE code=?1", nativeQuery = true) 14 | Project getProject(String code); 15 | 16 | @Query(value = "SELECT idx FROM project WHERE code=?1", nativeQuery = true) 17 | Long getKeyByCode(String code); 18 | 19 | @Transactional 20 | void deleteByCode(String code); 21 | 22 | 23 | } 24 | 25 | /* 26 | Interface JpaRepository 27 | 28 | * 29 | * CrudRepository, PagingAndSortingRepository, QueryByExampleExecutor, Repository 30 | * 31 | 32 | All MethodsInstance MethodsAbstract Methods 33 | Modifier and Type Method and Description 34 | 35 | void deleteAllInBatch() 36 | Deletes all entities in a batch call. 37 | 38 | void deleteInBatch(Iterable entities) 39 | Deletes the given entities in a batch which means it will create a single Query. 40 | 41 | List findAll() 42 | 43 | 44 | List findAll(Example example) 45 | 46 | 47 | List findAll(Example example, Sort sort) 48 | 49 | List findAll(Sort sort) 50 | 51 | List findAllById(Iterable ids) 52 | 53 | void flush() 54 | Flushes all pending changes to the database. 55 | 56 | T getOne(ID id) 57 | Returns a reference to the entity with the given identifier. 58 | 59 | 60 | List saveAll(Iterable entities) 61 | 62 | 63 | S saveAndFlush(S entity) 64 | Saves an entity and flushes changes instantly. 65 | 66 | */ 67 | -------------------------------------------------------------------------------- /src/main/java/com/sw/project/repository/subProblemRepository.java: -------------------------------------------------------------------------------- 1 | package com.sw.project.repository; 2 | 3 | import org.springframework.data.jpa.repository.JpaRepository; 4 | import org.springframework.data.jpa.repository.Query; 5 | import org.springframework.stereotype.Repository; 6 | 7 | import com.sw.project.domain.subProblem; 8 | 9 | @Repository 10 | public interface subProblemRepository extends JpaRepository{ 11 | 12 | @Query(value = "SELECT * FROM subproblem WHERE code=?1", nativeQuery = true) 13 | subProblem getSubProblem(int idx); 14 | 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/sw/project/service/ProblemService.java: -------------------------------------------------------------------------------- 1 | package com.sw.project.service; 2 | 3 | import java.util.Optional; 4 | 5 | import com.sw.project.domain.Problem; 6 | 7 | public interface ProblemService { 8 | 9 | Optional getProblemById(Long idx); 10 | 11 | Boolean saveProblem(Problem problem); 12 | //Proejct에 연결해서 저장만 하면 됨. 13 | 14 | Boolean deleteAllProblemWithCode(String code); //Problem삭제 -> Foreign key 문제 15 | 16 | Boolean deleteSubProblemByCodeInQuery(String code); //-> Subproblem 만 삭제 17 | 18 | Boolean deleteAllProblemAndSubWithCode(String code); //둘다 삭제 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/sw/project/service/ProblemServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.sw.project.service; 2 | 3 | import java.util.Optional; 4 | 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Service; 9 | 10 | import com.sw.project.domain.Problem; 11 | import com.sw.project.repository.ProblemRepository; 12 | 13 | @Service("problemService") 14 | public class ProblemServiceImpl implements ProblemService{ 15 | 16 | private Logger logger = LoggerFactory.getLogger(this.getClass()); 17 | 18 | @Autowired 19 | private ProblemRepository problemRepository; 20 | 21 | @Override 22 | public Optional getProblemById(Long idx) { 23 | // TODO Auto-generated method stub 24 | 25 | return Optional.ofNullable(problemRepository.getProblem(idx)); 26 | } 27 | 28 | 29 | @Override 30 | public Boolean saveProblem(Problem problem) { 31 | 32 | if(problem.getTitle() == null) { //have to fix it !!!!!!!!!!!!!!!!!!!!! 33 | return false; 34 | } 35 | problemRepository.saveAndFlush(problem); 36 | return true; 37 | } 38 | 39 | @Override 40 | public Boolean deleteAllProblemWithCode(String code) { 41 | // TODO Auto-generated method stub 42 | 43 | try { 44 | problemRepository.deleteAllProblemByCodeInQuery(code); 45 | return true; 46 | 47 | }catch(Exception e) { 48 | return false; 49 | } 50 | } 51 | 52 | @Override 53 | public Boolean deleteSubProblemByCodeInQuery(String code) { 54 | // TODO Auto-generated method stub 55 | try { 56 | problemRepository.deleteAllSubProblemByCodeInQuery(code); 57 | return true; 58 | }catch(Exception e) { 59 | return false; 60 | } 61 | } 62 | 63 | @Override 64 | public Boolean deleteAllProblemAndSubWithCode(String code) { 65 | 66 | try{ 67 | problemRepository.deleteAllSubProblemByCodeInQuery(code); 68 | problemRepository.deleteAllProblemByCodeInQuery(code); 69 | return true; 70 | 71 | }catch(Exception e) { 72 | return false; 73 | } 74 | 75 | 76 | } 77 | } 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /src/main/java/com/sw/project/service/ProjectService.java: -------------------------------------------------------------------------------- 1 | package com.sw.project.service; 2 | 3 | import java.util.Optional; 4 | 5 | import com.sw.project.domain.Project; 6 | 7 | public interface ProjectService { 8 | 9 | String saveProject(Project project); 10 | Boolean updateProject(Project project); 11 | Optional findProjectByCode(String code); 12 | Boolean deleteProject(String code); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/sw/project/service/ProjectServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.sw.project.service; 2 | 3 | import java.util.Optional; 4 | 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Service; 9 | 10 | import com.sw.project.domain.Project; 11 | import com.sw.project.repository.ProjectRepository; 12 | 13 | @Service("projectService") 14 | public class ProjectServiceImpl implements ProjectService{ 15 | 16 | private Logger logger = LoggerFactory.getLogger(this.getClass()); 17 | @Autowired 18 | private ProjectRepository projectRepository; 19 | 20 | @Override 21 | public String saveProject(Project project) { 22 | 23 | //validateProjectCode(project); 24 | try { 25 | projectRepository.saveAndFlush(project); 26 | return "1"; 27 | }catch(Exception e) { 28 | 29 | return e.getMessage(); 30 | } 31 | 32 | } 33 | 34 | @Override 35 | public Optional findProjectByCode(String code) { //code를 ipt로 해당 Project 정보 추출s 36 | 37 | return Optional.ofNullable(projectRepository.getProject(code)); 38 | } 39 | 40 | 41 | @Override 42 | public Boolean deleteProject(String code) { 43 | // TODO Auto-generated method stub 44 | try { 45 | projectRepository.deleteByCode(code); 46 | logger.info("Code !!"); 47 | return true; 48 | }catch(Exception e) { 49 | logger.info(e.getMessage()); 50 | return false; 51 | } 52 | } 53 | 54 | @Override 55 | public Boolean updateProject(Project project) { 56 | 57 | if(projectRepository.saveAndFlush(project).equals(null)) 58 | return false; 59 | 60 | return true; 61 | } 62 | 63 | } 64 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /src/main/java/com/sw/project/service/subProblemService.java: -------------------------------------------------------------------------------- 1 | package com.sw.project.service; 2 | 3 | import java.util.Optional; 4 | 5 | import com.sw.project.domain.subProblem; 6 | 7 | public interface subProblemService { 8 | 9 | Boolean saveSubProblem(subProblem subproblem); 10 | Optional getSubProblemById(int idx); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/sw/project/service/subProblemServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.sw.project.service; 2 | 3 | import java.util.Optional; 4 | 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Service; 7 | 8 | import com.sw.project.domain.subProblem; 9 | import com.sw.project.repository.subProblemRepository; 10 | 11 | @Service("subProblemService") 12 | public class subProblemServiceImpl implements subProblemService{ 13 | 14 | 15 | @Autowired 16 | private subProblemRepository subproblemRepository; 17 | 18 | @Override 19 | public Boolean saveSubProblem(subProblem subproblem) { 20 | 21 | try { 22 | subproblemRepository.saveAndFlush(subproblem); 23 | return true; 24 | 25 | }catch(Exception e) { 26 | return false; 27 | } 28 | } 29 | 30 | @Override 31 | public Optional getSubProblemById(int idx) { 32 | // TODO Auto-generated method stub 33 | return Optional.ofNullable(subproblemRepository.getSubProblem(idx)); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/sw/project/swagger/SwaggerConfig.java: -------------------------------------------------------------------------------- 1 | package com.sw.project.swagger; 2 | 3 | import io.swagger.v3.oas.models.OpenAPI; 4 | import io.swagger.v3.oas.models.info.Info; 5 | import io.swagger.v3.oas.models.info.License; 6 | import org.springframework.beans.factory.annotation.Value; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | 10 | @Configuration 11 | public class SwaggerConfig { 12 | 13 | @Bean 14 | public OpenAPI customOpenAPI(@Value("${application-description}") String appDescription, @Value("${application" + 15 | "-version}") String appVersion) { 16 | return new OpenAPI() 17 | .info(new Info() 18 | .title("Relationship Application API") 19 | .version(appVersion) 20 | .description(appDescription) 21 | .termsOfService("http://swagger.io/terms/") 22 | .license(new License().name("Apache 2.0").url("http://springdoc.org"))); 23 | 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | application: 3 | name: project-api 4 | 5 | ## Hibernate Properties 6 | # The SQL dialect makes Hibernate generate better SQL for the chosen database 7 | jpa: 8 | properties: 9 | hibernate: 10 | dialect: org.hibernate.dialect.MySQLDialect 11 | format_sql: true 12 | # Hibernate ddl auto (create, create-drop, validate, update) 13 | hibernate: 14 | ddl-auto: update 15 | 16 | show-sql: true 17 | datasource: 18 | url: jdbc:mysql://{YOUR_MSQL_SERVER}:3306/{DATABASE NAME}?useSSL=false 19 | username: { YOUR_MYSQL_ID } 20 | password: { YOUR_MYSQL_PASSWORD } 21 | driver-class-name: com.mysql.cj.jdbc.Driver 22 | hikari: 23 | maximum-pool-size: 2 24 | 25 | server: 26 | port: 8080 27 | 28 | application-description: '@project.description@' 29 | application-version: '@project.version@' 30 | # swagger-ui custom path 31 | springdoc: 32 | version: '@springdoc.version@' 33 | swagger-ui: 34 | path: /swagger-ui 35 | api-docs: 36 | path: /v3/api-docs 37 | -------------------------------------------------------------------------------- /src/test/java/com/sw/project/ProjectApiApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.sw.project; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class ProjectApiApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | --------------------------------------------------------------------------------