Spring Boot CRUD API ๊ตฌํ (2) - Repository, Service, Controller ๊ณ์ธต ๊ตฌํ (Member)
by rlaehddnd0422์ด๋ฒ ํฌ์คํ ์์๋ Repository ๊ณ์ธต ๋ฐ Service ๊ณ์ธต์ ๊ตฌํํด๋ณด๊ฒ ์ต๋๋ค.
์ค์ ๋ฐ์ด๋ฒํ ์ด์ค(h2) DataSource ์ค์
๋ณธ ํ๋ก์ ํธ์์๋ ์๋์ ๊ฐ์ด JDBC๋ฅผ ์ง์ ์ฌ์ฉํด์ ๋ฒ๊ฑฐ๋กญ๊ฒ DriverManger์์ ๋งค๋ฒ ์ปค๋ฅ์ ์ ํ๋ํ์ง ์๊ณ ,
Connection connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);
JDBC์ ์์ ORM(๊ฐ์ฒด ๊ด๊ณ ๋งคํ) ๊ธฐ์ ์ธ JPA๋ฅผ ํตํด JDBC์ ์ ๊ทผํ์ฌ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ํ ์ปค๋ฅ์ ์ ํ๋ํ๊ธฐ ๋๋ฌธ์
๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ํ ์ปค๋ฅ์ ์ ๋ณด๋ฅผ ์ ํ๋ฆฌ์ผ์ด์ ๋ถํธ์ ์ ๋ ฅํด์ ์ค์ DB์ ์ ๊ทผํ๋๋ก ์ค์ ํ์์ต๋๋ค.
์ค์ DB์ ์ ๊ทผํ๊ธฐ ์ํ DataSource๋ฅผ ์ ํ๋ฆฌ์ผ์ด์ ๋ถํธ ์ ๋ณด์ ์ค์ ํด์ค์๋ค. ( application.yml ) / h2 Database ์ฌ์ฉ
spring:
datasource:
url: jdbc:h2:tcp://localhost/~/board
username: sa
password:
driver-class-name: org.h2.Driver
jpa:
hibernate:
ddl-auto:
default_batch_fetch_size: 1000
properties:
hibernate:
show_sql: true
format_sql: true
logging.level:
org.hibernate.SQL: debug
Repository ๊ณ์ธต - Member
Spring Data JPA๋ฅผ ์ฌ์ฉํด ๊ตฌํํ์์ต๋๋ค.
public interface MemberRepository extends JpaRepository<Member,Long> {
Optional<Member> findByNickname(String nickName);
Optional<Member> findByEmail(String email);
}
Service ๊ณ์ธต ๊ตฌํ - Member
MemberService
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class MemberService {
private final MemberRepository memberRepository;
@Transactional
public MemberResponseDto save(MemberRequestDto memberRequestDto) {
Member member = memberRepository.save(new Member(memberRequestDto));
return MemberResponseDto.toDto(member);
}
@Transactional
public MemberResponseDto update(Long id, MemberEditRequestDto memberEditRequestDto) {
Member member = memberRepository.findById(id).orElseThrow(MemberNotFoundException::new);
member.updateMember(memberEditRequestDto);
return MemberResponseDto.toDto(member);
}
public MemberResponseDto findByNickname(String nickName) {
Member member = memberRepository.findByNickname(nickName).orElseThrow(MemberNotFoundException::new);
log.info("member = {} ",member.getEmail());
return MemberResponseDto.toDto(member);
}
@Transactional
public void delete(Long id) {
Member member = memberRepository.findById(id).orElseThrow(MemberNotFoundException::new);
memberRepository.delete(member);
}
}
- ๋ฆฌํฌ์งํ ๋ฆฌ ๊ณ์ธต์ ์ ๊ทผํด ๋ฉค๋ฒ ์ ์ฅ, ์์ , ์กฐํ, ์ญ์ ํ๋ ๋ก์ง
- @Transactional : ์ค์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋ฐ์ดํฐ ๋ณ๋์ฌํญ์ด ์๋ ๋ฉ์๋์ ๊ฑธ์ด์ฃผ์ด, ํ๋ก์ AOP๋ฅผ ํตํด ํธ๋์ญ์ ์์, ์ปค๋ฐ(๋กค๋ฐฑ) ์ฒ๋ฆฌํ๋๋ก ์ค์ ( ์กฐํ๋ฅผ ์ ์ธํ ๋๋จธ์ง ๋ฉ์๋ )
- @Transactional(readOnly = true) : ์ฝ๊ธฐ ์ ์ฉ @Transactional / ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ค์ ๋ณ๋์ฌํญ์ด ์๋ ๋ฉ์๋
- ๋ง์ฐฌ๊ฐ์ง๋ก commit ๋ ์ฝ๊ธฐ ๋ชจ๋๊ฐ ์๋ ์ ์ฉ
Controller ๊ณ์ธต ๊ตฌํ - Member
@RestController
@RequiredArgsConstructor
@RequestMapping("/member")
public class MemberController {
private final MemberService memberService;
@PostMapping
public Response memberSave(@Valid @RequestBody MemberRequestDto memberRequestDto) {
MemberResponseDto memberResponseDto = memberService.save(memberRequestDto);
return Response.success(memberResponseDto);
}
@PatchMapping("/{id}")
public Response memberEdit(@PathVariable Long id, @Valid @RequestBody MemberEditRequestDto memberEditRequestDto) {
MemberResponseDto memberResponseDto = memberService.update(id, memberEditRequestDto);
return Response.success(memberResponseDto);
}
@DeleteMapping("/{id}")
public Response memberDelete(@PathVariable Long id) {
memberService.delete(id);
return Response.success("ํ์ ์ญ์ ์๋ฃ");
}
}
- ๋ฑ๋ก, ์์ : MemberRequestDto์ ๊ฒ์ฆ๋ ๊ฐ๋ง json ํ์์ผ๋ก Request ํด์ฌ Service ๊ณ์ธต์ ์ ๊ทผํด์ ๋ฆฌํฌ์งํ ๋ฆฌ ๊ณ์ธต์์ ๋ฑ๋ก ๋ฐ ์์
- ์ญ์ : Service ๊ณ์ธต์ ์ ๊ทผํด์ ์ญ์ ๋ฉ์๋ ์คํ
- Response๋ ResponseEntity<T> ๊ฐ ์๋ ์ง์ ๋ง๋ค์ด ์ฌ์ฉํ์์ต๋๋ค. (์๋ ์ฐธ๊ณ )
Member
๊ธฐ๋ฅ ๋ฉ์๋ URL RETURN TYPE
ํ์ ๋ฑ๋ก | POST | /member/save | MemberResponseDto |
ํ์ ์์ | PATCH | /member/patch/{id} | MemberResponseDto |
ํ์ ์ญ์ | DELETE | /members | "ํ์ ์ญ์ ์๋ฃ" |
Response Type
@JsonInclude(JsonInclude.Include.NON_NULL) // null ๋
ธ์ถ x
@AllArgsConstructor(access = AccessLevel.PRIVATE) // ์ ๊ทผ ๋ ๋ฒจ private
@Getter
public class Response {
private boolean success;
private int code;
private Result result;
public static Response success() {
return new Response(true, 0, null);
}
public static <T> Response success(T data) {
return new Response(true,0,new Success<>(data));
}
public static Response failure(int code, String msg) {
return new Response(false,code,new Failure(msg));
}
}
public interface Result {
}
์์ฒญ ์ฑ๊ณต ์
@JsonInclude(JsonInclude.Include.NON_NULL) // null ํ๋ ๋
ธ์ถ X
@Getter
@AllArgsConstructor(access = AccessLevel.PROTECTED)
public class Success<T> implements Result {
private T data;
}
์์ฒญ ์คํจ ์
@JsonInclude(JsonInclude.Include.NON_NULL)
@Getter
@AllArgsConstructor(access = AccessLevel.PROTECTED)
public class Failure implements Result {
String msg;
}
'๐ Backend' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๋ธ๋ก๊ทธ์ ์ ๋ณด
Study Repository
rlaehddnd0422