๋ชฉ์ฐจ

Spring Boot์ JPA ์ด๊ฐ๋จ CRUD REST API ์์(๋ด๊ฐ ๋ณด๊ธฐ ์ํด ๊ธฐ๋ก)
๋ผ์ด๋ธ์ฝ๋ฉ(์๊ฐ ์ ๋ง์ด ๋ณต๋ถ ํจ) ๐ถ
h2 database ver: H2 2.1.214 (2022-06-13)

build.gradle ๐
plugins {
id 'org.springframework.boot' version '2.6.11'
id 'io.spring.dependency-management' version '1.0.13.RELEASE'
id 'java'
}
group = 'com.devlsy'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-devtools'
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.h2database:h2'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
tasks.named('test') {
useJUnitPlatform()
}
domain ๐
DTO(ํ๋ก ํธ์ ๋ฐ์ดํฐ๋ง ์ฃผ๊ณ ๋ฐ๋ ์ฉ๋)
entity๋ ์ ๋๋ก ํ๋ ์ ํ ์ด์ ๊ณ์ธต๊ณผ ํต์ ํ๋ฉด ์๋๊ธฐ์ ํ๋ ์ ํ ์ด์ ๊ณ์ธต๊ณผ ํต์ ํ๋ ์ฉ๋์ธ DTO๋ฅผ ๋ฐ๋ก ์์ฑํด์ ์ด๋์ผ๋ก๋ง ํด๋ผ์ด์ธํธ์ ํต์
DB์ ๊ฐ์ ์ํฐํฐ์ ๋ด๊ณ ์ํฐํฐ์์ ํ์ํ ๋ฐ์ดํฐ๋ง DTO์ ๋ด์์ DTO๋ฅผ ์ต์ข ์ ์ผ๋ก ํด๋ผ์ด์ธํธ์ ๋ฐํ
package com.devlsy.devlsyjpa.domain;
import lombok.Builder;
import lombok.Getter;
import lombok.Setter;
import java.time.LocalDateTime;
@Getter @Setter
@Builder
public class MemberDTO {
private Long memberId;
private String name;
private String email;
private LocalDateTime regDate;
private LocalDateTime updateDate;
// convert entity to dto
public static MemberDTO fromEntity(MemberEntity member) {
return MemberDTO.builder()
.memberId(member.getMemberId())
.name(member.getName())
.email(member.getEmail())
.regDate(member.getRegDate())
.updateDate(member.getUpdateDate())
.build();
}
}
Entity(JPA ๊ด๋ฆฌ ์ฃผ์ฒด)
์์์ฑ ์ปจํ ์คํธ์์ ๊ด๋ฆฌํ๋ ์ํฐํฐ๋ ๋ถ๋ณ๊ฐ์ฒด์ฌ์ผ ํ๋ฏ๋ก getter๋ง ์ด์ด๋๊ณ ๊ฐ์ฒด ์์ฑ ์์ ์ builderํจํด์ผ๋ก ์์ฑํ ์ ์๋๋ก ์ค์
package com.devlsy.devlsyjpa.domain;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;
import javax.persistence.*;
import java.time.LocalDateTime;
@Entity
@Getter
@NoArgsConstructor
@Table(name = "member_test")
public class MemberEntity {
@Id @GeneratedValue
@Column(name = "member_id")
private Long memberId;
private String name;
private String email;
@CreationTimestamp
@Column(name = "reg_date", updatable = false)
private LocalDateTime regDate;
@UpdateTimestamp
@Column(name = "update_date")
private LocalDateTime updateDate;
@Builder
public MemberEntity(Long memberId, String name, String email, LocalDateTime regDate, LocalDateTime updateDate) {
this.memberId = memberId;
this.name = name;
this.email = email;
this.regDate = regDate;
this.updateDate = updateDate;
}
}
Controller ๐
๊ฐ์ฒด ์ฃผ์ ์ ์์ฑ์ ํจํด ์ฌ์ฉ
// @RequiredArgsConstructor ์ด ์ด๋
ธํ
์ด์
์ ์๋์ ์ฝ๋๋ฅผ ๋กฌ๋ณต์ ์ด์ฉํด์ ์๋์์ฑํด์ค๋ค.(ํ๋์ final์ด๋ @NotNull์ด ๋ถ์ ์์ฑ์๋ฅผ ์๋์ผ๋ก ์์ฑํด์ค)
// @RequiredArgsConstructor ์ด ์ด๋
ธํ
์ด์
์ฌ์ฉ ์ํ ๊ฒฝ์ฐ ์๋์ฒ๋ผ ์ฝ๋๋ฅผ ์
๋ ฅํด์ผ ํจ, ์ฅ๋จ์ด ์๊ณ ํ๋๊ฐ ์ฌ๋ฌ๊ฐ ์ผ ๊ฒฝ์ฐ ์ข ์ง์ ๋ถํด ์ง์๋ ์์
@Autowired
public MemberController(MemberService memberService, EtcService etcService, GoodService goodService, BadService badService) {
this.memberService = memberService;
this.etcService = etcService;
this.goodService = goodService;
this.badService = badService;
}
package com.devlsy.devlsyjpa.controller;
import com.devlsy.devlsyjpa.domain.MemberDTO;
import com.devlsy.devlsyjpa.service.MemberService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@Slf4j
@RestController
@RequiredArgsConstructor
public class MemberController {
private final MemberService memberService;
// ๋ฉค๋ฒ ๋ฑ๋ก
@PostMapping("/")
public Long createMember(@RequestBody MemberDTO memberDTO) {
return memberService.createMember(memberDTO);
}
// ๋ฉค๋ฒ ์กฐํ
@GetMapping("/{memberId}")
public MemberDTO findOneMember(@PathVariable Long memberId) {
return memberService.findMember(memberId);
}
// ๋ฉค๋ฒ ๋ชฉ๋ก ์กฐํ
@GetMapping("/")
public List<MemberDTO> findAllMember() {
return memberService.findAllList();
}
// ๋ฉค๋ฒ ์ญ์
@DeleteMapping("/{memberId}")
public void deleteMember(@PathVariable Long memberId) {
memberService.deleteMember(memberId);
}
}
Service ๐ค
๊ฐ์ฒด ์ฃผ์ ์ ์์ฑ์ ํจํด ์ฌ์ฉ
package com.devlsy.devlsyjpa.service;
import com.devlsy.devlsyjpa.domain.MemberDTO;
import com.devlsy.devlsyjpa.domain.MemberEntity;
import com.devlsy.devlsyjpa.repository.MemberRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
@Service
@Slf4j
@RequiredArgsConstructor
public class MemberService {
private final MemberRepository memberRepository;
/**
* ๋ฉค๋ฒ ๋ฆฌ์คํธ ์กฐํ
* @return
*/
@Transactional(readOnly = true)
public List<MemberDTO> findAllList() {
List<MemberEntity> memberEntityList = memberRepository.findAll();
// ์ผ๋ฐ foreach(java 1.5 ์ด์)
// List<MemberDTO> memberDTOList = new ArrayList<>();
// for (MemberEntity member: memberEntityList) {
// memberDTOList.add(MemberDTO.fromEntity(member));
// }
// return memberDTOList;
// java 1.8 stream ์ด์ฉ
List<MemberDto> result = memberEntityList.stream()
.map(m -> toDto(m)).collect(toList());
return result;
}
/**
* ๋ฉค๋ฒ ๋จ๊ฑด ์กฐํ
* @param
* @return
*/
@Transactional(readOnly = true)
public MemberDTO findMember(Long memberId) {
MemberEntity findMember = memberRepository.findByMemberId(memberId);
return MemberDTO.fromEntity(findMember);
}
/**
* ๋ฉค๋ฒ ๋จ๊ฑด ์ญ์
* @param
* @return
*/
@Transactional
public void deleteMember(Long memberId) {
memberRepository.deleteByMemberId(memberId);
}
/**
* ๋ฉค๋ฒ ๋ฑ๋ก
* @param
* @return
*/
@Transactional
public Long createMember(MemberDTO memberDTO) {
MemberEntity member = MemberEntity.builder()
.memberId(memberDTO.getMemberId())
.name(memberDTO.getName())
.email(memberDTO.getEmail())
.build();
MemberEntity save = memberRepository.save(member);
return save.getMemberId();
}
}
Repository ๐
JPA ์์ ๊ด๋ จ JpaRepository๋ฅผ ์์๋ฐ์ ์ธํฐํ์ด์ค
package com.devlsy.devlsyjpa.repository;
import com.devlsy.devlsyjpa.domain.MemberEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface MemberRepository extends JpaRepository<MemberEntity, Long> {
// ๋ฉค๋ฒ ๋จ๊ฑด ์กฐํ
public MemberEntity findByMemberId(Long memberId);
// ๋ฉค๋ฒ ๋จ๊ฑด ์ญ์
public void deleteByMemberId(Long memberId);
}
application.yml ๐
spring:
datasource:
url: jdbc:h2:tcp://localhost/~/jpashop
username: sa
password:
# h2 database ์ฌ์ฉ
driver-class-name: org.h2.Driver
jpa:
hibernate:
# ๋ก์ปฌ์์ ์ ๋ง ํธ๋ฆฌํ ์ต์
ddl-auto: create
properties:
hibernate:
show_sql: true
format_sql : true
database-platform: org.hibernate.dialect.H2Dialect
logging:
level:
org.hivernate.SQL: debug
org.hivernate.type: trace
์ด๋ ๊ฒ ํ๋ฉด ๊ฐ๋ฐ ๋์ด๋ค.(SQL์ ๋ด๊ฐ ์์ฑํ ์ฝ๋๊ฐ ์ ํ ์๋ค.)
ibatis/mybatis์์ ์์ฑํ๋ SQL๋ฌธ์ ์๋ ์ด๋ค.
ibatis/mybatis์์ ","๊ณผ ๊ฐ์ ์คํ์ ๋๋ฌธ์ ์๋ฌ ์ก๋๋ผ ์๊ฐ์ ๋ณด๋๋ ๋ ๋ค์ด ์ฃผ๋ง๋ฑ์ฒ๋ผ ์ค์ณ๊ฐ๋ค.
JPA๋ฅผ ๊ณ์ ๊ณต๋ถํ๊ณ ์๋ ์ ์ฅ์ด๊ณ ํ์ต ๋์ด๋๊ฐ ์์ง๋ง ์ ๋๋ก ์ฌ์ฉํ๋ฉด ์ ๋ง ์์ฐ/์ ์ง๋ณด์ ๋ฑ ์ฌ๋ฌ๋ฐฉ๋ฉด์์ ์๋นํ ํจ๊ณผ๊ฐ ๋ ๋ฏ ์ถ๋ค.
์์ง์ ์๋ฐฉํฅ ์ฐ๊ด๊ด๊ณ๋ ๊ฐ์๋ง ๋ฃ๊ณ ์ค์ ํผ์ ํด๋ณด๊ณ ๋ด๊ป๋ก ๋ง๋ค์ง ์์๊ธฐ์ ๊ทธ๊ฒ์ ๋์ค์ ๊ธฐ๋กํ ์์
ํ ์คํธ(postman ์ด์ฉ)
ํ์ ๋ฑ๋ก



ํ์ ์ญ์



ํ ์คํธ ๋ฐ์ดํฐ ๋ช๊ฐ ๋ฃ๊ณ ์กฐํ


ํ์ ๋จ๊ฑด ์กฐํ


ํ์ ์์ ์ ์ฐ์ ์๋ต(JPA์์๋ ๋ํฐ ์ฒดํน์ ์ด์ฉํด ํธ๋์ญ์ ์ปค๋ฐ ์์ ์ด์ ์ ํ๋๊ฐ์ด ๋ณ๊ฒฝ๋๋ฉด ๋ฐ๋ ๋ด์ฉ์ DB์ commitํ๋ค.)
save ํ๋ฒ์ผ๋ก update๊น์ง ํ ์ ์๋ค.
์ ์ฒด ์ฝ๋: https://github.com/devLsy/devlsyjpa

'IT > development' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
| [IDE] intellJ IDEA live template ์์ฑ (0) | 2022.11.21 |
|---|---|
| [mybatis] mybatis ์ด์ค foreach insert(feat. ์ด์ค ๊ณ์ธต ๊ฐ์ฒด ์ ์ฅ) (0) | 2022.11.21 |
| [jpa] querydsl ์ธํ (feat. ํ๊ฒฝ์ค์ ๋ง ๋ค๋ฃธ) (1) | 2022.11.21 |
| [mybatis] mybatis ๋ฐฐ์ด ์ ์ฅ(feat. foreach) (0) | 2022.11.21 |
| [mybatis] mybatis ๋์ ์ฟผ๋ฆฌ(feat. <where></where>) (0) | 2022.11.20 |
๋๊ธ