# Spring Boot CRUD API ๊ตฌํ˜„ (2) - Repository, Service, Controller ๊ณ„์ธต ๊ตฌํ˜„ (Member)
Study Repository

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;
}

 

๋ธ”๋กœ๊ทธ์˜ ์ •๋ณด

Study Repository

rlaehddnd0422

ํ™œ๋™ํ•˜๊ธฐ