From 22028f03afc0a794d7924e7813310626f8917e28 Mon Sep 17 00:00:00 2001 From: shoeone96 Date: Sun, 19 Nov 2023 22:31:10 +0900 Subject: [PATCH 01/11] =?UTF-8?q?weekly=20mission=201=EC=A3=BC=EC=B0=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 202 ++++++++++++++++++ HELP.md | 28 +++ build.gradle | 39 ++++ docker-compose.yml | 17 ++ mysql/Dockerfile | 6 + mysql/init.sql | 5 + settings.gradle | 1 + src/main/java/com/example/jpa/Customer.java | 48 +++++ .../com/example/jpa/CustomerController.java | 34 +++ .../com/example/jpa/CustomerRepository.java | 6 + .../com/example/jpa/CustomerResponseDto.java | 15 ++ .../example/jpa/CustomerSaveRequestDto.java | 9 + .../java/com/example/jpa/CustomerService.java | 42 ++++ .../example/jpa/CustomerUpdateRequestDto.java | 8 + .../java/com/example/jpa/JpaApplication.java | 13 ++ src/main/resources/application.yaml | 9 + .../com/example/jpa/JpaApplicationTests.java | 13 ++ 17 files changed, 495 insertions(+) create mode 100644 .gitignore create mode 100644 HELP.md create mode 100644 build.gradle create mode 100644 docker-compose.yml create mode 100644 mysql/Dockerfile create mode 100644 mysql/init.sql create mode 100644 settings.gradle create mode 100644 src/main/java/com/example/jpa/Customer.java create mode 100644 src/main/java/com/example/jpa/CustomerController.java create mode 100644 src/main/java/com/example/jpa/CustomerRepository.java create mode 100644 src/main/java/com/example/jpa/CustomerResponseDto.java create mode 100644 src/main/java/com/example/jpa/CustomerSaveRequestDto.java create mode 100644 src/main/java/com/example/jpa/CustomerService.java create mode 100644 src/main/java/com/example/jpa/CustomerUpdateRequestDto.java create mode 100644 src/main/java/com/example/jpa/JpaApplication.java create mode 100644 src/main/resources/application.yaml create mode 100644 src/test/java/com/example/jpa/JpaApplicationTests.java diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..523eb4c48 --- /dev/null +++ b/.gitignore @@ -0,0 +1,202 @@ +# Created by https://www.toptal.com/developers/gitignore/api/intellij+all,macos,gradle,visualstudiocode,java +# Edit at https://www.toptal.com/developers/gitignore?templates=intellij+all,macos,gradle,visualstudiocode,java + +### Intellij+all ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +gradlew.bat +gradlew +gradle/** + + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### Intellij+all Patch ### +# Ignore everything but code style settings and run configurations +# that are supposed to be shared within teams. + +.idea/* + +!.idea/codeStyles +!.idea/runConfigurations + +### Java ### +# Compiled class file +*.class + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* +replay_pid* + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### macOS Patch ### +# iCloud generated files +*.icloud + +### VisualStudioCode ### +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets + +# Local History for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions +*.vsix + +### VisualStudioCode Patch ### +# Ignore all local history of files +.history +.ionide + +### Gradle ### +.gradle +**/build/ +!src/**/build/ + +# Ignore Gradle GUI config +gradle-app.setting + +# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) +!gradle-wrapper.jar + +# Avoid ignore Gradle wrappper properties +!gradle-wrapper.properties + +# Cache of project +.gradletasknamecache + +# Eclipse Gradle plugin generated files +# Eclipse Core +.project +# JDT-specific (Eclipse Java Development Tools) +.classpath + +### Gradle Patch ### +# Java heap dump +*.hprof + +# End of https://www.toptal.com/developers/gitignore/api/intellij+all,macos,gradle,visualstudiocode,java \ No newline at end of file diff --git a/HELP.md b/HELP.md new file mode 100644 index 000000000..59c3de046 --- /dev/null +++ b/HELP.md @@ -0,0 +1,28 @@ +# Getting Started + +### Reference Documentation + +For further reference, please consider the following sections: + +* [Official Gradle documentation](https://docs.gradle.org) +* [Spring Boot Gradle Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/3.1.5/gradle-plugin/reference/html/) +* [Create an OCI image](https://docs.spring.io/spring-boot/docs/3.1.5/gradle-plugin/reference/html/#build-image) +* [Spring Data JPA](https://docs.spring.io/spring-boot/docs/3.1.5/reference/htmlsingle/index.html#data.sql.jpa-and-spring-data) +* [Spring Web](https://docs.spring.io/spring-boot/docs/3.1.5/reference/htmlsingle/index.html#web) + +### Guides + +The following guides illustrate how to use some features concretely: + +* [Accessing data with MySQL](https://spring.io/guides/gs/accessing-data-mysql/) +* [Accessing Data with JPA](https://spring.io/guides/gs/accessing-data-jpa/) +* [Building a RESTful Web Service](https://spring.io/guides/gs/rest-service/) +* [Serving Web Content with Spring MVC](https://spring.io/guides/gs/serving-web-content/) +* [Building REST services with Spring](https://spring.io/guides/tutorials/rest/) + +### Additional Links + +These additional references should also help you: + +* [Gradle Build Scans – insights for your project's build](https://scans.gradle.com#gradle) + diff --git a/build.gradle b/build.gradle new file mode 100644 index 000000000..3ee78e16a --- /dev/null +++ b/build.gradle @@ -0,0 +1,39 @@ +plugins { + id 'java' + id 'org.springframework.boot' version '3.1.5' + id 'io.spring.dependency-management' version '1.1.3' +} + +group = 'com.example' +version = '0.0.1-SNAPSHOT' + +java { + sourceCompatibility = '17' +} + +configurations { + compileOnly { + extendsFrom annotationProcessor + } +} + +repositories { + mavenCentral() +} + +dependencies { + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation 'org.springframework.boot:spring-boot-starter-web' + compileOnly 'org.projectlombok:lombok' + runtimeOnly 'com.mysql:mysql-connector-j' + annotationProcessor 'org.projectlombok:lombok' + testImplementation 'org.springframework.boot:spring-boot-starter-test' +} + +tasks.named('bootBuildImage') { + builder = 'paketobuildpacks/builder-jammy-base:latest' +} + +tasks.named('test') { + useJUnitPlatform() +} diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 000000000..74fcbe45c --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,17 @@ +version: "3.8" + +services: + mysql: + build: + context: ./mysql + dockerfile: Dockerfile + ports: + - "3300:3306" + volumes: + - "data_volume:/var/lib/mysql" + environment: + MYSQL_PASSWORD: "test" + MYSQL_ROOT_PASSWORD: "test" + MYSQL_DATABASE: "test" +volumes: + data_volume: \ No newline at end of file diff --git a/mysql/Dockerfile b/mysql/Dockerfile new file mode 100644 index 000000000..89e1e729b --- /dev/null +++ b/mysql/Dockerfile @@ -0,0 +1,6 @@ +# Use the official MySQL 8 image as the base image +FROM mysql:8 +ENV MYSQL_ROOT_PASSWORD=test +ENV MYSQL_DATABASE=test +ENV MYSQL_ROOT_USER=root +COPY init.sql /docker-entrypoint-initdb.d/ \ No newline at end of file diff --git a/mysql/init.sql b/mysql/init.sql new file mode 100644 index 000000000..fa1331aaf --- /dev/null +++ b/mysql/init.sql @@ -0,0 +1,5 @@ +CREATE DATABASE IF NOT EXISTS test; + +USE test; + + diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 000000000..b9c66803a --- /dev/null +++ b/settings.gradle @@ -0,0 +1 @@ +rootProject.name = 'jpa' diff --git a/src/main/java/com/example/jpa/Customer.java b/src/main/java/com/example/jpa/Customer.java new file mode 100644 index 000000000..71b2f84c3 --- /dev/null +++ b/src/main/java/com/example/jpa/Customer.java @@ -0,0 +1,48 @@ +package com.example.jpa; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Entity +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class Customer { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String username; + private String password; + private String name; + private String nickname; + @Builder + private Customer (String name, String nickname, String password, String username){ + this.name = name; + this.nickname = nickname; + this.password = password; + this.username = username; + } + + public static Customer of(CustomerSaveRequestDto requestDto) { + return Customer.builder() + .name(requestDto.name()) + .nickname(requestDto.nickname()) + .password(requestDto.password()) + .username(requestDto.username()) + .build(); + } + + public Long updateInfo(CustomerUpdateRequestDto requestDto) { + this.username = requestDto.username(); + this.password = requestDto.password(); + this.nickname = requestDto.nickname(); + return this.id; + } +} diff --git a/src/main/java/com/example/jpa/CustomerController.java b/src/main/java/com/example/jpa/CustomerController.java new file mode 100644 index 000000000..6e95d14ca --- /dev/null +++ b/src/main/java/com/example/jpa/CustomerController.java @@ -0,0 +1,34 @@ +package com.example.jpa; + +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/customers") +public class CustomerController { + + private final CustomerService customerService; + + @GetMapping() + public List getCustomerList(){ + return customerService.getCustomers(); + } + + @PostMapping() + public Long saveNewCustomer(@RequestBody CustomerSaveRequestDto requestDto){ + return customerService.saveCustomer(requestDto); + } + + @PatchMapping("/{customerId}") + public Long updateCustomerInfo(@RequestBody CustomerUpdateRequestDto requestDto, @PathVariable Long customerId){ + return customerService.updateCustomer(requestDto, customerId); + } + + @DeleteMapping("/{customerId}") + public Long deleteCustomer(@PathVariable Long customerId){ + return customerService.deleteCustomer(customerId); + } +} diff --git a/src/main/java/com/example/jpa/CustomerRepository.java b/src/main/java/com/example/jpa/CustomerRepository.java new file mode 100644 index 000000000..8f6c3dcc4 --- /dev/null +++ b/src/main/java/com/example/jpa/CustomerRepository.java @@ -0,0 +1,6 @@ +package com.example.jpa; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface CustomerRepository extends JpaRepository { +} diff --git a/src/main/java/com/example/jpa/CustomerResponseDto.java b/src/main/java/com/example/jpa/CustomerResponseDto.java new file mode 100644 index 000000000..b3e9b1d7b --- /dev/null +++ b/src/main/java/com/example/jpa/CustomerResponseDto.java @@ -0,0 +1,15 @@ +package com.example.jpa; + +public record CustomerResponseDto ( + Long customerId, + String username, + String nickname +){ + + public static CustomerResponseDto of(Customer customer) { + return new CustomerResponseDto( + customer.getId(), + customer.getUsername(), + customer.getNickname()); + } +} diff --git a/src/main/java/com/example/jpa/CustomerSaveRequestDto.java b/src/main/java/com/example/jpa/CustomerSaveRequestDto.java new file mode 100644 index 000000000..8744518d4 --- /dev/null +++ b/src/main/java/com/example/jpa/CustomerSaveRequestDto.java @@ -0,0 +1,9 @@ +package com.example.jpa; + +public record CustomerSaveRequestDto ( + String username, + String nickname, + String password, + String name +){ +} diff --git a/src/main/java/com/example/jpa/CustomerService.java b/src/main/java/com/example/jpa/CustomerService.java new file mode 100644 index 000000000..6487ba76b --- /dev/null +++ b/src/main/java/com/example/jpa/CustomerService.java @@ -0,0 +1,42 @@ +package com.example.jpa; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.NoSuchElementException; + +@Service +@RequiredArgsConstructor +public class CustomerService { + + private final CustomerRepository customerRepository; + public List getCustomers() { + return customerRepository.findAll() + .stream() + .map(CustomerResponseDto::of) + .toList(); + } + + public Long saveCustomer(CustomerSaveRequestDto requestDto) { + Customer customer = Customer.of(requestDto); + return customerRepository.save(customer).getId(); + } + + @Transactional + public Long updateCustomer(CustomerUpdateRequestDto requestDto, Long customerId) { + Customer findCustomer = customerRepository.findById(customerId) + .orElseThrow(() -> new NoSuchElementException("해당 유저를 찾을 수 없습니다.")); + findCustomer.updateInfo(requestDto); + return findCustomer.getId(); + } + + @Transactional + public Long deleteCustomer(Long customerId) { + Customer findCustomer = customerRepository.findById(customerId) + .orElseThrow(() -> new NoSuchElementException("해당 유저를 찾을 수 없습니다.")); + customerRepository.delete(findCustomer); + return findCustomer.getId(); + } +} diff --git a/src/main/java/com/example/jpa/CustomerUpdateRequestDto.java b/src/main/java/com/example/jpa/CustomerUpdateRequestDto.java new file mode 100644 index 000000000..dada66f1a --- /dev/null +++ b/src/main/java/com/example/jpa/CustomerUpdateRequestDto.java @@ -0,0 +1,8 @@ +package com.example.jpa; + +public record CustomerUpdateRequestDto( + String username, + String password, + String nickname +) { +} diff --git a/src/main/java/com/example/jpa/JpaApplication.java b/src/main/java/com/example/jpa/JpaApplication.java new file mode 100644 index 000000000..2f5b36153 --- /dev/null +++ b/src/main/java/com/example/jpa/JpaApplication.java @@ -0,0 +1,13 @@ +package com.example.jpa; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class JpaApplication { + + public static void main(String[] args) { + SpringApplication.run(JpaApplication.class, args); + } + +} diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml new file mode 100644 index 000000000..ebffb6ebd --- /dev/null +++ b/src/main/resources/application.yaml @@ -0,0 +1,9 @@ +spring: + datasource: + url: jdbc:mysql://localhost:3300/test + username: root + password: test + driver-class-name: com.mysql.cj.jdbc.Driver + jpa: + hibernate: + ddl-auto: update diff --git a/src/test/java/com/example/jpa/JpaApplicationTests.java b/src/test/java/com/example/jpa/JpaApplicationTests.java new file mode 100644 index 000000000..0a3b69476 --- /dev/null +++ b/src/test/java/com/example/jpa/JpaApplicationTests.java @@ -0,0 +1,13 @@ +package com.example.jpa; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class JpaApplicationTests { + + @Test + void contextLoads() { + } + +} From b99e7b842abdfe911bdc048aa23bdc8167a2bac3 Mon Sep 17 00:00:00 2001 From: shoeone96 Date: Sun, 19 Nov 2023 23:13:19 +0900 Subject: [PATCH 02/11] =?UTF-8?q?faet:=20sql=20=EB=AC=B8=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mysql/init.sql | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/mysql/init.sql b/mysql/init.sql index fa1331aaf..8484bdd67 100644 --- a/mysql/init.sql +++ b/mysql/init.sql @@ -1,5 +1,27 @@ -CREATE DATABASE IF NOT EXISTS test; +CREATE +DATABASE IF NOT EXISTS test; USE test; +create table customers +( + id bigint primary key , + username varchar(20), + name varchar(20), + password varchar(50), + nickname varchar(20) +); + +CREATE +DATABASE IF NOT EXISTS test_code; +USE test_code; + +create table customers +( + id bigint primary key , + username varchar(20), + name varchar(20), + password varchar(50), + nickname varchar(20) +); \ No newline at end of file From fb7d84c2064b87a753523c2d88b06904ed52b70e Mon Sep 17 00:00:00 2001 From: shoeone96 Date: Sun, 19 Nov 2023 23:13:40 +0900 Subject: [PATCH 03/11] =?UTF-8?q?faet:=20table=20=EB=AA=85=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/example/jpa/Customer.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/example/jpa/Customer.java b/src/main/java/com/example/jpa/Customer.java index 71b2f84c3..6b4acd467 100644 --- a/src/main/java/com/example/jpa/Customer.java +++ b/src/main/java/com/example/jpa/Customer.java @@ -1,9 +1,6 @@ package com.example.jpa; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; +import jakarta.persistence.*; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; @@ -12,6 +9,7 @@ @Entity @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) +@Table(name = "customers") public class Customer { @Id From 687284c0d1ec01697a7d61691e863e59b5f9977e Mon Sep 17 00:00:00 2001 From: shoeone96 Date: Sun, 19 Nov 2023 23:18:26 +0900 Subject: [PATCH 04/11] =?UTF-8?q?refactor:=20private=20=EC=83=9D=EC=84=B1?= =?UTF-8?q?=EC=9E=90=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/example/jpa/Customer.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/example/jpa/Customer.java b/src/main/java/com/example/jpa/Customer.java index 6b4acd467..da9540853 100644 --- a/src/main/java/com/example/jpa/Customer.java +++ b/src/main/java/com/example/jpa/Customer.java @@ -20,7 +20,7 @@ public class Customer { private String password; private String name; private String nickname; - @Builder + private Customer (String name, String nickname, String password, String username){ this.name = name; this.nickname = nickname; @@ -29,12 +29,12 @@ private Customer (String name, String nickname, String password, String username } public static Customer of(CustomerSaveRequestDto requestDto) { - return Customer.builder() - .name(requestDto.name()) - .nickname(requestDto.nickname()) - .password(requestDto.password()) - .username(requestDto.username()) - .build(); + return new Customer( + requestDto.name(), + requestDto.nickname(), + requestDto.password(), + requestDto.username() + ); } public Long updateInfo(CustomerUpdateRequestDto requestDto) { From 9b742919bee0fbd7e57ff5a476f1acf045dafe35 Mon Sep 17 00:00:00 2001 From: shoeone96 Date: Sun, 19 Nov 2023 23:18:49 +0900 Subject: [PATCH 05/11] =?UTF-8?q?feat:=20=EB=8B=A8=20=EA=B1=B4=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20api=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/example/jpa/CustomerController.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/example/jpa/CustomerController.java b/src/main/java/com/example/jpa/CustomerController.java index 6e95d14ca..515e0d16b 100644 --- a/src/main/java/com/example/jpa/CustomerController.java +++ b/src/main/java/com/example/jpa/CustomerController.java @@ -13,17 +13,22 @@ public class CustomerController { private final CustomerService customerService; @GetMapping() - public List getCustomerList(){ + public List getCustomerList() { return customerService.getCustomers(); } + @GetMapping("/{customerId}") + public CustomerResponseDto getCustomer(@PathVariable Long customerId) { + return customerService.getCustomer(customerId); + } + @PostMapping() - public Long saveNewCustomer(@RequestBody CustomerSaveRequestDto requestDto){ + public Long saveNewCustomer(@RequestBody CustomerSaveRequestDto requestDto) { return customerService.saveCustomer(requestDto); } @PatchMapping("/{customerId}") - public Long updateCustomerInfo(@RequestBody CustomerUpdateRequestDto requestDto, @PathVariable Long customerId){ + public Long updateCustomerInfo(@RequestBody CustomerUpdateRequestDto requestDto, @PathVariable Long customerId) { return customerService.updateCustomer(requestDto, customerId); } From 0253d92f651969ae9d0becaa05fd74718211cba2 Mon Sep 17 00:00:00 2001 From: shoeone96 Date: Sun, 19 Nov 2023 23:19:19 +0900 Subject: [PATCH 06/11] =?UTF-8?q?refactor:=20=EA=B3=B5=ED=86=B5=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C(findById())=20=EB=A9=94=EC=84=9C=EB=93=9C=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/example/jpa/CustomerService.java | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/example/jpa/CustomerService.java b/src/main/java/com/example/jpa/CustomerService.java index 6487ba76b..6b70fa55e 100644 --- a/src/main/java/com/example/jpa/CustomerService.java +++ b/src/main/java/com/example/jpa/CustomerService.java @@ -12,6 +12,7 @@ public class CustomerService { private final CustomerRepository customerRepository; + public List getCustomers() { return customerRepository.findAll() .stream() @@ -26,17 +27,24 @@ public Long saveCustomer(CustomerSaveRequestDto requestDto) { @Transactional public Long updateCustomer(CustomerUpdateRequestDto requestDto, Long customerId) { - Customer findCustomer = customerRepository.findById(customerId) - .orElseThrow(() -> new NoSuchElementException("해당 유저를 찾을 수 없습니다.")); - findCustomer.updateInfo(requestDto); - return findCustomer.getId(); + Customer findCustomer = findCustomer(customerId); + return findCustomer.updateInfo(requestDto); } @Transactional public Long deleteCustomer(Long customerId) { - Customer findCustomer = customerRepository.findById(customerId) - .orElseThrow(() -> new NoSuchElementException("해당 유저를 찾을 수 없습니다.")); + Customer findCustomer = findCustomer(customerId); customerRepository.delete(findCustomer); return findCustomer.getId(); } + + public CustomerResponseDto getCustomer(Long customerId) { + return CustomerResponseDto.of(findCustomer(customerId)); + } + + private Customer findCustomer(Long customerId) { + Customer findCustomer = customerRepository.findById(customerId) + .orElseThrow(() -> new NoSuchElementException("해당 유저를 찾을 수 없습니다.")); + return findCustomer; + } } From 7ccf02f9f6650083a2ad194bfb938cc39ca13d7e Mon Sep 17 00:00:00 2001 From: shoeone96 Date: Sun, 19 Nov 2023 23:19:44 +0900 Subject: [PATCH 07/11] =?UTF-8?q?chore:=20yaml=20=ED=8C=8C=EC=9D=BC=20test?= =?UTF-8?q?=20=EC=BD=94=EB=93=9C=20=EC=82=AC=EC=9A=A9=20=EC=A0=84=EC=9A=A9?= =?UTF-8?q?=20=EB=94=B0=EB=A1=9C=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application.yaml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index ebffb6ebd..0fb5c2042 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -7,3 +7,16 @@ spring: jpa: hibernate: ddl-auto: update +--- +spring: + datasource: + url: jdbc:mysql://localhost:3300/test_code + username: root + password: test + driver-class-name: com.mysql.cj.jdbc.Driver + jpa: + hibernate: + ddl-auto: update + config: + activate: + on-profile: test \ No newline at end of file From de3fcf3e40dfc4145f21d5a4f594e271af7e504b Mon Sep 17 00:00:00 2001 From: shoeone96 Date: Sun, 19 Nov 2023 23:20:03 +0900 Subject: [PATCH 08/11] =?UTF-8?q?test:=20=EA=B0=81=20=ED=95=B5=EC=8B=AC=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EA=B0=84=EB=8B=A8=ED=95=9C=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/example/jpa/CustomerServiceTest.java | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 src/test/java/com/example/jpa/CustomerServiceTest.java diff --git a/src/test/java/com/example/jpa/CustomerServiceTest.java b/src/test/java/com/example/jpa/CustomerServiceTest.java new file mode 100644 index 000000000..f25e611f8 --- /dev/null +++ b/src/test/java/com/example/jpa/CustomerServiceTest.java @@ -0,0 +1,95 @@ +package com.example.jpa; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.annotation.Rollback; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.NoSuchElementException; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +@ActiveProfiles("test") +@SpringBootTest +@Transactional +class CustomerServiceTest { + + @Autowired + CustomerService customerService; + + @Test + @DisplayName("정상적으로 등록되는 경우의 테스트") + @Rollback + public void insertTest() throws Exception { + + //given + CustomerSaveRequestDto requestDto = new CustomerSaveRequestDto("username", "nickname", "password", "name"); + + //when + Long newCustomerId = customerService.saveCustomer(requestDto); + CustomerResponseDto customer = customerService.getCustomer(newCustomerId); + + //then + assertThat(newCustomerId).isEqualTo(customer.customerId()); + } + + + @Test + @DisplayName("정상적으로 모든 데이터를 불러오는 경우의 테스트") + public void getTest() throws Exception { + + //given + CustomerSaveRequestDto requestDto = new CustomerSaveRequestDto("username", "nickname", "password", "name"); + + //when + Long newCustomerId = customerService.saveCustomer(requestDto); + List customers = customerService.getCustomers(); + + //then + assertThat(customers).hasSize(1); + } + + + @Test + @DisplayName("정상적으로 모든 수정하는 경우의 테스트") + public void updateTest() throws Exception { + + //given + CustomerSaveRequestDto requestDto = new CustomerSaveRequestDto("username", "nickname", "password", "name"); + CustomerUpdateRequestDto updateRequestDto = new CustomerUpdateRequestDto("username update", "nickname update", "password update"); + + //when + Long newCustomerId = customerService.saveCustomer(requestDto); + customerService.updateCustomer(updateRequestDto, newCustomerId); + + CustomerResponseDto customer = customerService.getCustomer(newCustomerId); + //then + assertThat(customer.nickname()).isEqualTo(updateRequestDto.nickname()); + assertThat(customer.username()).isEqualTo(updateRequestDto.username()); + + } + + @Test + @DisplayName("정상적으로 삭제하는 경우의 테스트") + public void deleteTest() throws Exception { + + //given + CustomerSaveRequestDto requestDto = new CustomerSaveRequestDto("username", "nickname", "password", "name"); + CustomerUpdateRequestDto updateRequestDto = new CustomerUpdateRequestDto("username update", "nickname update", "password update"); + + //when + Long newCustomerId = customerService.saveCustomer(requestDto); + customerService.deleteCustomer(newCustomerId); + + assertThatThrownBy(() -> customerService.getCustomer(newCustomerId)) + .isInstanceOf(NoSuchElementException.class) + .hasMessage("해당 유저를 찾을 수 없습니다."); + + } + +} \ No newline at end of file From 9d4ee2bae47505edd0cb2ec021f6e1eb909b91d3 Mon Sep 17 00:00:00 2001 From: shoeone96 Date: Fri, 24 Nov 2023 18:01:53 +0900 Subject: [PATCH 09/11] feat: week2 --- .../example/jpa/{ => customer}/Customer.java | 21 ++- .../{ => customer}/CustomerController.java | 2 +- .../{ => customer}/CustomerRepository.java | 3 +- .../{ => customer}/CustomerResponseDto.java | 2 +- .../CustomerSaveRequestDto.java | 2 +- .../jpa/{ => customer}/CustomerService.java | 2 +- .../CustomerUpdateRequestDto.java | 2 +- .../jpa/customer/JpaCustomerRepository.java | 68 ++++++++ .../java/com/example/jpa/order/Order.java | 49 ++++++ .../example/jpa/order/OrderRepository.java | 6 + .../com/example/jpa/order/OrderStatus.java | 5 + .../com/example/jpa/orderItem/BaseEntity.java | 16 ++ .../java/com/example/jpa/orderItem/Item.java | 34 ++++ .../example/jpa/orderItem/ItemRepository.java | 6 + .../com/example/jpa/orderItem/OrderItem.java | 43 +++++ .../jpa/orderItem/OrderItemRepository.java | 6 + src/main/resources/application.yaml | 4 +- .../com/example/jpa/CustomerServiceTest.java | 4 + .../example/jpa/PersistenceContextTest.java | 161 ++++++++++++++++++ 19 files changed, 423 insertions(+), 13 deletions(-) rename src/main/java/com/example/jpa/{ => customer}/Customer.java (66%) rename src/main/java/com/example/jpa/{ => customer}/CustomerController.java (97%) rename src/main/java/com/example/jpa/{ => customer}/CustomerRepository.java (80%) rename src/main/java/com/example/jpa/{ => customer}/CustomerResponseDto.java (90%) rename src/main/java/com/example/jpa/{ => customer}/CustomerSaveRequestDto.java (80%) rename src/main/java/com/example/jpa/{ => customer}/CustomerService.java (97%) rename src/main/java/com/example/jpa/{ => customer}/CustomerUpdateRequestDto.java (78%) create mode 100644 src/main/java/com/example/jpa/customer/JpaCustomerRepository.java create mode 100644 src/main/java/com/example/jpa/order/Order.java create mode 100644 src/main/java/com/example/jpa/order/OrderRepository.java create mode 100644 src/main/java/com/example/jpa/order/OrderStatus.java create mode 100644 src/main/java/com/example/jpa/orderItem/BaseEntity.java create mode 100644 src/main/java/com/example/jpa/orderItem/Item.java create mode 100644 src/main/java/com/example/jpa/orderItem/ItemRepository.java create mode 100644 src/main/java/com/example/jpa/orderItem/OrderItem.java create mode 100644 src/main/java/com/example/jpa/orderItem/OrderItemRepository.java create mode 100644 src/test/java/com/example/jpa/PersistenceContextTest.java diff --git a/src/main/java/com/example/jpa/Customer.java b/src/main/java/com/example/jpa/customer/Customer.java similarity index 66% rename from src/main/java/com/example/jpa/Customer.java rename to src/main/java/com/example/jpa/customer/Customer.java index da9540853..dc9a6757c 100644 --- a/src/main/java/com/example/jpa/Customer.java +++ b/src/main/java/com/example/jpa/customer/Customer.java @@ -1,14 +1,18 @@ -package com.example.jpa; +package com.example.jpa.customer; +import com.example.jpa.order.Order; import jakarta.persistence.*; -import lombok.AccessLevel; -import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.util.ArrayList; +import java.util.List; @Entity @Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Setter +@NoArgsConstructor @Table(name = "customers") public class Customer { @@ -21,7 +25,10 @@ public class Customer { private String name; private String nickname; - private Customer (String name, String nickname, String password, String username){ + @OneToMany(mappedBy = "customer", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true) + private List orders = new ArrayList<>(); + + private Customer(String name, String nickname, String password, String username) { this.name = name; this.nickname = nickname; this.password = password; @@ -43,4 +50,8 @@ public Long updateInfo(CustomerUpdateRequestDto requestDto) { this.nickname = requestDto.nickname(); return this.id; } + + public void addOrder(Order order) { + order.setMember(this); + } } diff --git a/src/main/java/com/example/jpa/CustomerController.java b/src/main/java/com/example/jpa/customer/CustomerController.java similarity index 97% rename from src/main/java/com/example/jpa/CustomerController.java rename to src/main/java/com/example/jpa/customer/CustomerController.java index 515e0d16b..016ee704e 100644 --- a/src/main/java/com/example/jpa/CustomerController.java +++ b/src/main/java/com/example/jpa/customer/CustomerController.java @@ -1,4 +1,4 @@ -package com.example.jpa; +package com.example.jpa.customer; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; diff --git a/src/main/java/com/example/jpa/CustomerRepository.java b/src/main/java/com/example/jpa/customer/CustomerRepository.java similarity index 80% rename from src/main/java/com/example/jpa/CustomerRepository.java rename to src/main/java/com/example/jpa/customer/CustomerRepository.java index 8f6c3dcc4..ad0813c40 100644 --- a/src/main/java/com/example/jpa/CustomerRepository.java +++ b/src/main/java/com/example/jpa/customer/CustomerRepository.java @@ -1,4 +1,5 @@ -package com.example.jpa; +package com.example.jpa.customer; + import org.springframework.data.jpa.repository.JpaRepository; diff --git a/src/main/java/com/example/jpa/CustomerResponseDto.java b/src/main/java/com/example/jpa/customer/CustomerResponseDto.java similarity index 90% rename from src/main/java/com/example/jpa/CustomerResponseDto.java rename to src/main/java/com/example/jpa/customer/CustomerResponseDto.java index b3e9b1d7b..0e218a7ab 100644 --- a/src/main/java/com/example/jpa/CustomerResponseDto.java +++ b/src/main/java/com/example/jpa/customer/CustomerResponseDto.java @@ -1,4 +1,4 @@ -package com.example.jpa; +package com.example.jpa.customer; public record CustomerResponseDto ( Long customerId, diff --git a/src/main/java/com/example/jpa/CustomerSaveRequestDto.java b/src/main/java/com/example/jpa/customer/CustomerSaveRequestDto.java similarity index 80% rename from src/main/java/com/example/jpa/CustomerSaveRequestDto.java rename to src/main/java/com/example/jpa/customer/CustomerSaveRequestDto.java index 8744518d4..baa7378f3 100644 --- a/src/main/java/com/example/jpa/CustomerSaveRequestDto.java +++ b/src/main/java/com/example/jpa/customer/CustomerSaveRequestDto.java @@ -1,4 +1,4 @@ -package com.example.jpa; +package com.example.jpa.customer; public record CustomerSaveRequestDto ( String username, diff --git a/src/main/java/com/example/jpa/CustomerService.java b/src/main/java/com/example/jpa/customer/CustomerService.java similarity index 97% rename from src/main/java/com/example/jpa/CustomerService.java rename to src/main/java/com/example/jpa/customer/CustomerService.java index 6b70fa55e..b74ac1503 100644 --- a/src/main/java/com/example/jpa/CustomerService.java +++ b/src/main/java/com/example/jpa/customer/CustomerService.java @@ -1,4 +1,4 @@ -package com.example.jpa; +package com.example.jpa.customer; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; diff --git a/src/main/java/com/example/jpa/CustomerUpdateRequestDto.java b/src/main/java/com/example/jpa/customer/CustomerUpdateRequestDto.java similarity index 78% rename from src/main/java/com/example/jpa/CustomerUpdateRequestDto.java rename to src/main/java/com/example/jpa/customer/CustomerUpdateRequestDto.java index dada66f1a..971e0babf 100644 --- a/src/main/java/com/example/jpa/CustomerUpdateRequestDto.java +++ b/src/main/java/com/example/jpa/customer/CustomerUpdateRequestDto.java @@ -1,4 +1,4 @@ -package com.example.jpa; +package com.example.jpa.customer; public record CustomerUpdateRequestDto( String username, diff --git a/src/main/java/com/example/jpa/customer/JpaCustomerRepository.java b/src/main/java/com/example/jpa/customer/JpaCustomerRepository.java new file mode 100644 index 000000000..6efcbb867 --- /dev/null +++ b/src/main/java/com/example/jpa/customer/JpaCustomerRepository.java @@ -0,0 +1,68 @@ +package com.example.jpa.customer; + +import jakarta.persistence.*; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.Optional; + +@Profile("test") +@Repository +@RequiredArgsConstructor +public class JpaCustomerRepository { + + private final EntityManager em; + + void save(Customer customer){ + EntityTransaction transaction = em.getTransaction(); + transaction.begin(); + + em.persist(customer); + + transaction.commit(); + } + + List findAll() { + EntityTransaction transaction = em.getTransaction(); + transaction.begin(); + + List customers = em.createQuery("select c from Customer c", Customer.class).getResultList(); + + transaction.commit(); + return customers; + } + + Optional findById(Long id){ + EntityTransaction transaction = em.getTransaction(); + transaction.begin(); + + Customer customerById = em.find(Customer.class, id); + Optional customer = Optional.ofNullable(customerById); + + transaction.commit(); + return customer; + } + + void update(Long id, CustomerUpdateRequestDto updatedCustomer){ + EntityTransaction transaction = em.getTransaction(); + transaction.begin(); + + Customer customerById = em.find(Customer.class, id); + customerById.updateInfo(updatedCustomer); + + transaction.commit(); + } + + void delete(Long id){ + EntityTransaction transaction = em.getTransaction(); + transaction.begin(); + + Customer customerById = em.find(Customer.class, id); + em.remove(customerById); + + transaction.commit(); + } + +} diff --git a/src/main/java/com/example/jpa/order/Order.java b/src/main/java/com/example/jpa/order/Order.java new file mode 100644 index 000000000..f869bdfe8 --- /dev/null +++ b/src/main/java/com/example/jpa/order/Order.java @@ -0,0 +1,49 @@ +package com.example.jpa.order; + +import com.example.jpa.customer.Customer; +import com.example.jpa.orderItem.OrderItem; +import jakarta.persistence.*; +import lombok.Getter; +import lombok.Setter; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Objects; + +@Entity +@Getter +@Setter +@Table(name = "orders") +public class Order { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + private String memo; + @Enumerated(EnumType.STRING) + private OrderStatus orderStatus; + private LocalDateTime orderDatetime; + + @Column(name = "customer_id", insertable = false, updatable = false) + private Long customerId; + //customer_fk + @ManyToOne + @JoinColumn(name = "customer_id", referencedColumnName = "id") + private Customer customer; + + @OneToMany(mappedBy = "order") + private List orderItems; + + public void setMember(Customer customer) { + if(Objects.nonNull(this.customer)) { + this.customer.getOrders().remove(this); + } + + this.customer = customer; + customer.getOrders().add(this); + } + + public void addOrderItem(OrderItem orderItem) { + orderItem.setOrder(this); + } +} diff --git a/src/main/java/com/example/jpa/order/OrderRepository.java b/src/main/java/com/example/jpa/order/OrderRepository.java new file mode 100644 index 000000000..da5341fcf --- /dev/null +++ b/src/main/java/com/example/jpa/order/OrderRepository.java @@ -0,0 +1,6 @@ +package com.example.jpa.order; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface OrderRepository extends JpaRepository { +} diff --git a/src/main/java/com/example/jpa/order/OrderStatus.java b/src/main/java/com/example/jpa/order/OrderStatus.java new file mode 100644 index 000000000..4d33957dd --- /dev/null +++ b/src/main/java/com/example/jpa/order/OrderStatus.java @@ -0,0 +1,5 @@ +package com.example.jpa.order; + +public enum OrderStatus { + OPENED, CANCELED +} diff --git a/src/main/java/com/example/jpa/orderItem/BaseEntity.java b/src/main/java/com/example/jpa/orderItem/BaseEntity.java new file mode 100644 index 000000000..f5351662f --- /dev/null +++ b/src/main/java/com/example/jpa/orderItem/BaseEntity.java @@ -0,0 +1,16 @@ +package com.example.jpa.orderItem; + +import jakarta.persistence.Column; +import jakarta.persistence.MappedSuperclass; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +@MappedSuperclass +public class BaseEntity { + @Column(name = "created_by") + private String createdBy; + @Column(name = "created_at", columnDefinition = "TIMESTAMP") + private LocalDateTime createdAt; +} \ No newline at end of file diff --git a/src/main/java/com/example/jpa/orderItem/Item.java b/src/main/java/com/example/jpa/orderItem/Item.java new file mode 100644 index 000000000..84ea5173e --- /dev/null +++ b/src/main/java/com/example/jpa/orderItem/Item.java @@ -0,0 +1,34 @@ +package com.example.jpa.orderItem; + +import jakarta.persistence.*; +import lombok.Getter; +import lombok.Setter; + +import java.util.Objects; + +@Entity +@Getter +@Setter +@Table(name = "item") +public class Item extends BaseEntity{ + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + private String itemName; + private int price; + private int stockQuantity; + + @ManyToOne + @JoinColumn(name = "order_item_id", referencedColumnName = "id") + private OrderItem orderItem; + + public void setOrderItem(OrderItem orderItem) { + if (Objects.nonNull(this.orderItem)) { + this.orderItem.getItems().remove(this); + } + + this.orderItem = orderItem; + orderItem.getItems().add(this); + } +} diff --git a/src/main/java/com/example/jpa/orderItem/ItemRepository.java b/src/main/java/com/example/jpa/orderItem/ItemRepository.java new file mode 100644 index 000000000..353cf1ccd --- /dev/null +++ b/src/main/java/com/example/jpa/orderItem/ItemRepository.java @@ -0,0 +1,6 @@ +package com.example.jpa.orderItem; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ItemRepository extends JpaRepository { +} diff --git a/src/main/java/com/example/jpa/orderItem/OrderItem.java b/src/main/java/com/example/jpa/orderItem/OrderItem.java new file mode 100644 index 000000000..18468ecf4 --- /dev/null +++ b/src/main/java/com/example/jpa/orderItem/OrderItem.java @@ -0,0 +1,43 @@ +package com.example.jpa.orderItem; + +import com.example.jpa.order.Order; +import jakarta.persistence.*; +import lombok.Getter; +import lombok.Setter; + +import java.util.List; +import java.util.Objects; + +@Entity +@Getter +@Setter +@Table(name = "order_item") +public class OrderItem extends BaseEntity{ + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private int price; + private int quantity; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "order_id", referencedColumnName = "id") + private Order order; + + @OneToMany(mappedBy = "orderItem") + private List items; + + public void setOrder(Order order) { + if (Objects.nonNull(this.order)) { + this.order.getOrderItems().remove(this); + } + + this.order = order; + order.getOrderItems().add(this); + } + + public void addItem(Item item) { + item.setOrderItem(this); + } +} diff --git a/src/main/java/com/example/jpa/orderItem/OrderItemRepository.java b/src/main/java/com/example/jpa/orderItem/OrderItemRepository.java new file mode 100644 index 000000000..9dbc1c6b3 --- /dev/null +++ b/src/main/java/com/example/jpa/orderItem/OrderItemRepository.java @@ -0,0 +1,6 @@ +package com.example.jpa.orderItem; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface OrderItemRepository extends JpaRepository { +} diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 0fb5c2042..3a93c72fe 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -6,7 +6,7 @@ spring: driver-class-name: com.mysql.cj.jdbc.Driver jpa: hibernate: - ddl-auto: update + ddl-auto: create --- spring: datasource: @@ -16,7 +16,7 @@ spring: driver-class-name: com.mysql.cj.jdbc.Driver jpa: hibernate: - ddl-auto: update + ddl-auto: create config: activate: on-profile: test \ No newline at end of file diff --git a/src/test/java/com/example/jpa/CustomerServiceTest.java b/src/test/java/com/example/jpa/CustomerServiceTest.java index f25e611f8..cb3dd4000 100644 --- a/src/test/java/com/example/jpa/CustomerServiceTest.java +++ b/src/test/java/com/example/jpa/CustomerServiceTest.java @@ -1,5 +1,9 @@ package com.example.jpa; +import com.example.jpa.customer.CustomerResponseDto; +import com.example.jpa.customer.CustomerSaveRequestDto; +import com.example.jpa.customer.CustomerService; +import com.example.jpa.customer.CustomerUpdateRequestDto; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; diff --git a/src/test/java/com/example/jpa/PersistenceContextTest.java b/src/test/java/com/example/jpa/PersistenceContextTest.java new file mode 100644 index 000000000..3b5540fa0 --- /dev/null +++ b/src/test/java/com/example/jpa/PersistenceContextTest.java @@ -0,0 +1,161 @@ +package com.example.jpa; + +import com.example.jpa.customer.Customer; +import com.example.jpa.customer.CustomerRepository; +import jakarta.persistence.EntityManager; +import jakarta.persistence.EntityManagerFactory; +import jakarta.persistence.EntityTransaction; + +import org.junit.jupiter.api.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; + + +import java.util.List; + +import static org.assertj.core.api.Assertions.*; + +@SpringBootTest +@ActiveProfiles("test") +public class PersistenceContextTest { + + @Autowired + EntityManagerFactory emf; + + @Autowired + CustomerRepository jpaCustomerRepository; + + static Customer customer; + static Customer customerSaved; + @BeforeEach + void setup(){ + customerSaved = new Customer(); + customerSaved.setName("name saved"); + customerSaved.setPassword("password saved"); + customerSaved.setNickname("nickname saved"); + + jpaCustomerRepository.save(customerSaved); + + + customer = new Customer(); + customer.setName("name"); + customer.setPassword("password"); + customer.setNickname("nickname"); + } + + @AfterEach + void clear(){ + jpaCustomerRepository.deleteAll(); + } + + @Test + @DisplayName("정상적으로 회원을 조회한다.") + void findSuccess(){ + EntityManager em = emf.createEntityManager(); + EntityTransaction transaction = em.getTransaction(); + transaction.begin(); + + List customers = em.createQuery("SELECT c FROM Customer c", Customer.class) + .getResultList(); + transaction.commit(); + em.close(); + + assertThat(customers).hasSize(1); + } + + @Test + @DisplayName("detach로 인한 update 실패") + void updateFailWithDetach(){ + EntityManager em = emf.createEntityManager(); + EntityTransaction transaction = em.getTransaction(); + transaction.begin(); + + em.persist(customer); + em.detach(customer); + customer.setUsername("test update"); + + transaction.commit(); + em.close(); + + List allCustomers = jpaCustomerRepository.findAll(); + assertThat(allCustomers.get(1).getName()).isEqualTo("name"); + } + + @Test + @DisplayName("정상적으로 회원을 저장한다.") + void saveSuccess(){ + EntityManager em = emf.createEntityManager(); + EntityTransaction transaction = em.getTransaction(); + transaction.begin(); + + em.persist(customer); + + transaction.commit(); + em.close(); + + List allCustomers = jpaCustomerRepository.findAll(); + assertThat(allCustomers).hasSize(2); + } + + + + @Test + @DisplayName("정상적으로 회원을 수정한다.(dirtyChecking)") + void updateSuccessWithDirtyChecking(){ + String updateName = "name update"; + + EntityManager em = emf.createEntityManager(); + EntityTransaction transaction = em.getTransaction(); + transaction.begin(); + + em.persist(customer); + customer.setName(updateName); + + transaction.commit(); + em.close(); + + Customer allCustomers = jpaCustomerRepository.findAll().get(1); + assertThat(allCustomers.getName()).isEqualTo(updateName); + } + @Test + @DisplayName("정상적으로 회원을 수정한다.(merge)") + void updateSuccessWithMerge(){ + String updateName = "name update"; + + EntityManager em = emf.createEntityManager(); + EntityTransaction transaction = em.getTransaction(); + transaction.begin(); + + em.persist(customer); + customer.setName(updateName); + em.merge(customer); + + transaction.commit(); + em.close(); + + Customer allCustomers = jpaCustomerRepository.findAll().get(1); + assertThat(allCustomers.getName()).isEqualTo(updateName); + } + @Test + @DisplayName("정상적으로 회원을 삭제한다.") + void deleteSuccess(){ + + Customer allCustomers = jpaCustomerRepository.findAll().get(0); + + + EntityManager em = emf.createEntityManager(); + EntityTransaction transaction = em.getTransaction(); + transaction.begin(); + + Customer customerById = em.find(Customer.class, allCustomers.getId()); + em.remove(customerById); + + transaction.commit(); + em.close(); + + List afterDelete = jpaCustomerRepository.findAll(); + + assertThat(afterDelete).hasSize(0); + } +} From dd8f2420a2690dd7970b591ba021bc78226958a7 Mon Sep 17 00:00:00 2001 From: shoeone96 Date: Sun, 26 Nov 2023 14:21:51 +0900 Subject: [PATCH 10/11] feat: week3 --- src/main/java/com/example/jpa/orderItem/Item.java | 2 ++ src/main/java/com/example/jpa/orderItem/OrderItem.java | 2 ++ src/main/resources/application.yaml | 1 + 3 files changed, 5 insertions(+) diff --git a/src/main/java/com/example/jpa/orderItem/Item.java b/src/main/java/com/example/jpa/orderItem/Item.java index 84ea5173e..177336e10 100644 --- a/src/main/java/com/example/jpa/orderItem/Item.java +++ b/src/main/java/com/example/jpa/orderItem/Item.java @@ -3,6 +3,7 @@ import jakarta.persistence.*; import lombok.Getter; import lombok.Setter; +import lombok.ToString; import java.util.Objects; @@ -10,6 +11,7 @@ @Getter @Setter @Table(name = "item") +@ToString public class Item extends BaseEntity{ @Id diff --git a/src/main/java/com/example/jpa/orderItem/OrderItem.java b/src/main/java/com/example/jpa/orderItem/OrderItem.java index 18468ecf4..556b96429 100644 --- a/src/main/java/com/example/jpa/orderItem/OrderItem.java +++ b/src/main/java/com/example/jpa/orderItem/OrderItem.java @@ -4,6 +4,7 @@ import jakarta.persistence.*; import lombok.Getter; import lombok.Setter; +import lombok.ToString; import java.util.List; import java.util.Objects; @@ -11,6 +12,7 @@ @Entity @Getter @Setter +@ToString @Table(name = "order_item") public class OrderItem extends BaseEntity{ diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 3a93c72fe..7f1327950 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -17,6 +17,7 @@ spring: jpa: hibernate: ddl-auto: create + show-sql: true config: activate: on-profile: test \ No newline at end of file From 0fc3f11d7fb38539d891813c8fae2e53c2dac5c1 Mon Sep 17 00:00:00 2001 From: shoeone96 Date: Sun, 26 Nov 2023 14:27:27 +0900 Subject: [PATCH 11/11] feat: week3 --- .../java/com/example/jpa/MappingTest.java | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 src/test/java/com/example/jpa/MappingTest.java diff --git a/src/test/java/com/example/jpa/MappingTest.java b/src/test/java/com/example/jpa/MappingTest.java new file mode 100644 index 000000000..059dc1ecf --- /dev/null +++ b/src/test/java/com/example/jpa/MappingTest.java @@ -0,0 +1,67 @@ +package com.example.jpa; + +import com.example.jpa.customer.Customer; + +import com.example.jpa.orderItem.Item; +import com.example.jpa.orderItem.OrderItem; +import jakarta.persistence.EntityManager; +import jakarta.persistence.EntityManagerFactory; +import jakarta.persistence.EntityTransaction; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; + +import java.util.List; + +@SpringBootTest +@ActiveProfiles("test") +public class MappingTest { + + private static final Logger log = LoggerFactory.getLogger(MappingTest.class); + + @Autowired + EntityManagerFactory emf; + + static Customer customer; + + static OrderItem orderItem; + static Item item; + @BeforeEach + void setUp(){ + customer = new Customer(); + customer.setNickname("nickname"); + customer.setName("name"); + customer.setPassword("password"); + + orderItem = new OrderItem(); + + item = new Item(); + item.setPrice(1000); + item.setStockQuantity(10); + item.setItemName("item"); + + } + + @Test + @DisplayName("연관관계 매핑") + void getMapping(){ + EntityManager em = emf.createEntityManager(); + EntityTransaction transaction = em.getTransaction(); + transaction.begin(); + em.persist(orderItem); + em.persist(item); + em.flush(); + em.clear(); + orderItem.setItems(List.of(item)); + log.info("{}", orderItem); + log.info("{}", item); + transaction.commit(); + em.close(); + } + +}