๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
Today I Learned(TIL)/์ŠคํŒŒ๋ฅดํƒ€ ๋‚ด์ผ๋ฐฐ์›€์บ ํ”„

์ฃผํŠน๊ธฐ ์ž…๋ฌธ/์ˆ™๋ จ_Day 14

by carrot0911 2024. 12. 12.

์˜ค๋Š˜ ํ•œ ๊ณต๋ถ€ ๐Ÿง 

  • ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋ฌธ์ œ(Java, SQL) 1๋ฌธ์ œ ํ’€์ด & ๋ธ”๋กœ๊ทธ ์ •๋ฆฌ
  • Spring ์ˆ™๋ จ ๊ฐ•์˜ ๋“ฃ๊ธฐ (3์ฃผ์ฐจ ์‹ค์Šต ํŒŒํŠธ)
  • Spring ์ˆ™๋ จ ๊ฐ•์˜ ๋‚ด์šฉ ๋ณต์Šต
  • TIL ๋ธ”๋กœ๊ทธ ์ž‘์„ฑ

 

์˜ค๋Š˜ ์–ป์€ ๋‚ด์šฉ ์ •๋ฆฌ โœ๏ธ 

์‹ค์Šต ํŒŒํŠธ ๋ณต์Šตํ•˜๋ฉด์„œ ๋‚ด์šฉ๋“ค ์ˆœ์„œ๋Œ€๋กœ ์ •๋ฆฌํ•ด์•ผ๊ฒ ๋‹ค.

1. JPA ๊ด€๋ จ ์„ค์ •ํ•˜๊ธฐ

๋”๋ณด๊ธฐ

DataSource ์„ค์ •

application.properties

spring.datasource.url=jdbc:mysql://localhost:3306/board
spring.datasource.username=๊ณ„์ •
spring.datasource.password=๋น„๋ฐ€๋ฒˆํ˜ธ
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

Hibernate ์„ค์ •

application.properties

spring.jpa.hibernate.ddl-auto=create

spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.use_sql_comments=true

spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect

2. Entity ์„ค๊ณ„

๋”๋ณด๊ธฐ

BaseEntity ์„ค๊ณ„ ๋ฐ ์ ์šฉํ•˜๊ธฐ

1. BaseEntity ํด๋ž˜์Šค

ํ•„๋“œ๋ช… ํƒ€์ž… ์„ค๋ช…
createdAt LocalDateTime ์ƒ์„ฑ ์‹œ๊ฐ„
updatedAt LocalDateTime ์ˆ˜์ • ์‹œ๊ฐ„

2. BaseEntity Entity ๊ตฌํ˜„

@Getter
@MappedSuperclass  // ํ•ด๋‹น ์–ด๋…ธํ…Œ์ด์…˜์ด ์„ ์–ธ๋œ ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›๋Š” Entity์— ๊ณตํ†ต ๋งคํ•‘ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•œ๋‹ค.
@EntityListeners(AuditingEntityListener.class)  // JPA Entity์˜ ์ƒ๋ช… ์ฃผ๊ธฐ ์ด๋ฒคํŠธ๋ฅผ ๊ฐ์ง€ํ•˜๊ณ , ํ•ด๋‹น ์ด๋ฒคํŠธ์— ๋”ฐ๋ผ ํŠน์ • ๋กœ์ง์„ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ์„ค์ •ํ•˜๋Š” Annotation
public abstract class BaseEntity {

    @CreatedDate
    @Column(updatable = false)
    // @Temporal(TemporalType.TIMESTAMP) // ์ƒ๋žต ๊ฐ€๋Šฅํ•˜๋‹ค.
    private LocalDateTime createdAt;

    @LastModifiedDate
    private LocalDateTime updatedAt;
}

3. @EnableJpaAuditing ์ ์šฉ

@EnableJpaAuditing
@SpringBootApplication
public class BoardApplication {

    public static void main(String[] args) {
        SpringApplication.run(JpaBoardApplication.class, args);
    }

}

 

ํšŒ์›(Member) ์„ค๊ณ„ํ•˜๊ธฐ

1. Member ํด๋ž˜์Šค

ํ•„๋“œ๋ช… ํƒ€์ž… ์„ค๋ช…
id Long ์‹๋ณ„์ž
username String ๋กœ๊ทธ์ธ์— ์‚ฌ์šฉํ•  ์•„์ด๋””
password String ๋กœ๊ทธ์ธ์— ์‚ฌ์šฉํ•  ๋น„๋ฐ€๋ฒˆํ˜ธ
age Integer ๋‚˜์ด
createdAt LocalDateTime ์ƒ์„ฑ ์‹œ๊ฐ„
updatedAt LocalDateTime ์ˆ˜์ • ์‹œ๊ฐ„

2. Member Entity ๊ตฌํ˜„

@Entity
@Table(name = "member")
public class Member extends BaseEntity{

    // ์†์„ฑ
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)  // JPA์—์„œ ๊ธฐ๋ณธ ํ‚ค(PK)๊ฐ’์„ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜์ด๋‹ค. GenerationType.IDENTITY๋Š” MySQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ์ž๋™ ์ฆ๊ฐ€ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•ด ๊ธฐ๋ณธ ํ‚ค๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
    private Long id;  // ๊ณ ์œ  ์‹๋ณ„์ž (์ž๋™์œผ๋กœ ์ƒ์„ฑ)

    @Column(nullable = false, unique = true)  // nullable์˜ ๊ธฐ๋ณธ๊ฐ’์€ true์ด๋‹ค.
    private String username;  // ๋กœ๊ทธ์ธํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ์•„์ด๋””

    @Column(nullable = false)
    private String password;  // ๋กœ๊ทธ์ธํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๋น„๋ฐ€๋ฒˆํ˜ธ

    private Integer age;  // ๋‚˜์ด

    // ์ƒ์„ฑ์ž


    // ๊ธฐ๋Šฅ
}

3. Application ์‹คํ–‰ ๋ฐ ๊ฒฐ๊ณผ ํ™•์ธ

member ํ…Œ์ด๋ธ”

 

๊ฒŒ์‹œ๊ธ€(Board) ์„ค๊ณ„ํ•˜๊ธฐ

1. Board ํด๋ž˜์Šค

ํ•„๋“œ๋ช… ํƒ€์ž… ์„ค๋ช…
id Long ์‹๋ณ„์ž
title String ์ œ๋ชฉ
contents String ๋‚ด์šฉ
createdAt LocalDateTime ์ƒ์„ฑ ์‹œ๊ฐ„
updatedAt LocalDateTime ์ˆ˜์ • ์‹œ๊ฐ„

2. Board Entity ๊ตฌํ˜„

@Entity
@Table(name = "board")
public class Board extends BaseEntity{

    // ์†์„ฑ
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false)
    private String title;

    @Column(columnDefinition = "longtext")
    private String contents;

    // ์ƒ์„ฑ์ž


    // ๊ธฐ๋Šฅ
}

3. Application ์‹คํ–‰ ๋ฐ ๊ฒฐ๊ณผ ํ™•์ธ

board ํ…Œ์ด๋ธ”

3. ์—ฐ๊ด€๊ด€๊ณ„ ์„ค์ •

๋”๋ณด๊ธฐ

์—ฐ๊ด€๊ด€๊ณ„ ์„ค์ •ํ•˜๊ธฐ

  • ํ•œ ๋ช…์˜ ํšŒ์›์€ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๊ฒŒ์‹œ๊ธ€์„ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค. (N:1 ๋‹จ๋ฐฉํ–ฅ)

1. Board Entity

@Entity
@Table(name = "board")
public class Board extends BaseEntity{

    // ์†์„ฑ
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false)
    private String title;

    @Column(columnDefinition = "longtext")
    private String contents;

    @ManyToOne
    @JoinColumn(name = "member_id")
    private Member member;

    // ์ƒ์„ฑ์ž


    // ๊ธฐ๋Šฅ
}

2. Application ์‹คํ–‰ ๋ฐ ๊ฒฐ๊ณผ ํ™•์ธ

์—ฐ๊ด€ ๊ด€๊ณ„ ํ™•์ธ

 

4. ํšŒ์› ์ƒ์„ฑ ๊ธฐ๋Šฅ

๋”๋ณด๊ธฐ

Member ์ƒ์„ฑ API ๊ตฌํ˜„

SignUpRequestDto

@Getter
public class SignUpReqeustDto {

    // ์†์„ฑ
    private final String username;

    private final String password;

    private final Integer age;

    // ์ƒ์„ฑ์ž
    public SignUpReqeustDto(String username, String password, Integer age) {
        this.username = username;
        this.password = password;
        this.age = age;
    }
    
    // ๊ธฐ๋Šฅ
}

SignUpResponseDto

@Getter
public class SignUpResponseDto {

    // ์†์„ฑ
    private final Long id;

    private final String username;

    private final Integer age;

    // ์ƒ์„ฑ์ž
    public SignUpResponseDto(Long id, String username, Integer age) {
        this.id = id;
        this.username = username;
        this.age = age;
    }
    
    // ๊ธฐ๋Šฅ
}

Member

@Getter
@Entity
@Table(name = "member")
public class Member extends BaseEntity{

    // ์†์„ฑ
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)  // JPA์—์„œ ๊ธฐ๋ณธ ํ‚ค(PK)๊ฐ’์„ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜์ด๋‹ค. GenerationType.IDENTITY๋Š” MySQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์˜ ์ž๋™ ์ฆ๊ฐ€ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•ด ๊ธฐ๋ณธ ํ‚ค๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
    private Long id;  // ๊ณ ์œ  ์‹๋ณ„์ž (์ž๋™์œผ๋กœ ์ƒ์„ฑ)

    @Column(nullable = false, unique = true)  // nullable์˜ ๊ธฐ๋ณธ๊ฐ’์€ true์ด๋‹ค.
    private String username;  // ๋กœ๊ทธ์ธํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ์•„์ด๋””

    @Column(nullable = false)
    private String password;  // ๋กœ๊ทธ์ธํ•  ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๋น„๋ฐ€๋ฒˆํ˜ธ

    private Integer age;  // ๋‚˜์ด

    // ์ƒ์„ฑ์ž
    public Member() {}
    
    public Member(String username, String password, Integer age) {
        this.username = username;
        this.password = password;
        this.age = age;
    }
    
    // ๊ธฐ๋Šฅ
}

MemberController

@RestController
@RequestMapping("/members")
@RequiredArgsConstructor
public class MemberController {

    // ์†์„ฑ
    private final MemberService memberService;

    // ์ƒ์„ฑ์ž


    // ๊ธฐ๋Šฅ
    @PostMapping("/signup")
    public ResponseEntity<SignUpResponseDto> signUp(@RequestBody SignUpReqeustDto reqeustDto) {

        SignUpResponseDto signUpResponseDto = memberService.signUp(reqeustDto.getUsername(), reqeustDto.getPassword(), reqeustDto.getAge());

        return new ResponseEntity<>(signUpResponseDto, HttpStatus.CREATED);
    }
}

MemberService

@Service
@RequiredArgsConstructor
public class MemberService {
    
    // ์†์„ฑ
    private final MemberRepository memberRepository;

    // ์ƒ์„ฑ์ž
    
    // ๊ธฐ๋Šฅ
    public SignUpResponseDto signUp(String username, String password, Integer age) {

        Member member = new Member(username, password, age);

        Member savedMember = memberRepository.save(member);

        return new SignUpResponseDto(savedMember.getId(), savedMember.getUsername(), savedMember.getAge());
    }
}
  • ํ™•์žฅํ•  ๊ฐ€๋Šฅ์„ฑ์ด ์—†๋‹ค๋ฉด Interface๊ฐ€ ์•„๋‹Œ ๊ตฌํ˜„์ฒด๋ฅผ ์˜์กดํ•ด๋„ ๋œ๋‹ค.

MemberRepository

public interface MemberRepository extends JpaRepository<Member, Long> {

    // ์†์„ฑ
    
    // ์ƒ์„ฑ์ž
    
    // ๊ธฐ๋Šฅ

}

5. ํŠน์ • ํšŒ์› ์กฐํšŒ ๊ธฐ๋Šฅ

๋”๋ณด๊ธฐ

ํŠน์ • Member ์กฐํšŒ API ๊ตฌํ˜„

MemberResponseDto

@Getter
public class MemberResponseDto {

    // ์†์„ฑ
    private final String username;

    private final Integer age;

    // ์ƒ์„ฑ์ž
    public MemberResponseDto(String username, Integer age) {
        this.username = username;
        this.age = age;
    }


    // ๊ธฐ๋Šฅ
}

MemberController

@RestController
@RequestMapping("/members")
@RequiredArgsConstructor
public class MemberController {

    // ์†์„ฑ
    private final MemberService memberService;

    // ์ƒ์„ฑ์ž


    // ๊ธฐ๋Šฅ
    @GetMapping("/{id}")
    public ResponseEntity<MemberResponseDto> findById(@PathVariable Long id) {

        MemberResponseDto memberResponseDto = memberService.findById(id);

        return new ResponseEntity<>(memberResponseDto, HttpStatus.OK);
    }
}

MemberService

@Service
@RequiredArgsConstructor
public class MemberService {

    // ์†์„ฑ
    private final MemberRepository memberRepository;

    // ์ƒ์„ฑ์ž

    // ๊ธฐ๋Šฅ
    public MemberResponseDto findById(Long id) {

        Optional<Member> optionalMember = memberRepository.findById(id);

        if (optionalMember.isEmpty()) {
            throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Does not exist id = " + id);
        }

        Member findMember = optionalMember.get();

        return new MemberResponseDto(findMember.getUsername(), findMember.getAge());
    }
}

6. ๋น„๋ฐ€๋ฒˆํ˜ธ ์ˆ˜์ • ๊ธฐ๋Šฅ

๋”๋ณด๊ธฐ

๋น„๋ฐ€๋ฒˆํ˜ธ ์ˆ˜์ • API ๊ตฌํ˜„

UpdatePasswordRequestDto

@Getter
public class UpdatePasswordRequestDto {

    // ์†์„ฑ
    private final String oldPassword;

    private final String newPassword;

    // ์ƒ์„ฑ์ž
    public UpdatePasswordRequestDto(String oldPassword, String newPassword) {
        this.oldPassword = oldPassword;
        this.newPassword = newPassword;
    }

    // ๊ธฐ๋Šฅ
}

MemberController

@RestController
@RequestMapping("/members")
@RequiredArgsConstructor
public class MemberController {

    // ์†์„ฑ
    private final MemberService memberService;

    // ์ƒ์„ฑ์ž


    // ๊ธฐ๋Šฅ
    @PatchMapping("/{id}")
    public ResponseEntity<Void> updatePassword(
            @PathVariable Long id,
            @RequestBody UpdatePasswordRequestDto requestDto
    ) {

        memberService.updatePassword(id, requestDto.getOldPassword(), requestDto.getNewPassword());

        return new ResponseEntity<>(HttpStatus.OK);
    }
}

MemberService

@Service
@RequiredArgsConstructor
public class MemberService {

    // ์†์„ฑ
    private final MemberRepository memberRepository;

    // ์ƒ์„ฑ์ž

    // ๊ธฐ๋Šฅ 
    @Transactional
    public void updatePassword(long id, String oldPassword, String newPassword) {

        Member findMember = memberRepository.findByIdOrElseThrow(id);

        if (!findMember.getPassword().equals(oldPassword)) {
            throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ์ผ์น˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.");
        }

        findMember.updatePassword(newPassword);
    }
}

Member

public void updatePassword(String password) {
    this.password = password;
}

MemberRepository

public interface MemberRepository extends JpaRepository<Member, Long> {


    // ์†์„ฑ

    // ์ƒ์„ฑ์ž

    // ๊ธฐ๋Šฅ
    default Member findByIdOrElseThrow(Long id) {

        return findById(id).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Does not exist id = " + id));
    }

}

7. ๊ฒŒ์‹œ๊ธ€ ์ƒ์„ฑ ๊ธฐ๋Šฅ

๋”๋ณด๊ธฐ

๊ฒŒ์‹œ๊ธ€ ์ƒ์„ฑ API ๊ตฌํ˜„

CreateBoardRequestDto

@Getter
public class CreateBoardReqeustDto {

    // ์†์„ฑ
    private final String title;

    private final String contents;

    private final String username;

    // ์ƒ์„ฑ์ž
    public CreateBoardReqeustDto(String title, String contents, String username) {
        this.title = title;
        this.contents = contents;
        this.username = username;
    }

    // ๊ธฐ๋Šฅ
}

BoardResponseDto

@Getter
public class BoardResponseDto {

    // ์†์„ฑ
    private final Long id;

    private final String title;

    private final String contents;

    // ์ƒ์„ฑ์ž
    public BoardResponseDto(Long id, String title, String contents) {
        this.id = id;
        this.title = title;
        this.contents = contents;
    }

    // ๊ธฐ๋Šฅ
}

Board

@Getter
@Entity
@Table(name = "board")
public class Board extends BaseEntity{

    // ์†์„ฑ
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false)
    private String title;

    @Column(columnDefinition = "longtext")
    private String contents;

    @ManyToOne
    @JoinColumn(name = "member_id")
    private Member member;

    // ์ƒ์„ฑ์ž
    public Board() {}

    public Board(String title, String contents) {
        this.title = title;
        this.contents = contents;
    }


    // ๊ธฐ๋Šฅ
    public void setMember(Member member) {
        this.member = member;
    }
}

BoardController

@RestController
@RequestMapping("/boards")
@RequiredArgsConstructor
public class BoardController {

    // ์†์„ฑ
    private final BoardService boardService;

    // ์ƒ์„ฑ์ž

    // ๊ธฐ๋Šฅ
    @PostMapping
    public ResponseEntity<BoardResponseDto> save(@RequestBody CreateBoardReqeustDto reqeustDto) {

        BoardResponseDto boardResponseDto = boardService.save(reqeustDto.getTitle(), reqeustDto.getContents(), reqeustDto.getUsername());

        return new ResponseEntity<>(boardResponseDto, HttpStatus.CREATED);
    }
}

BoardService

@Service
@RequiredArgsConstructor
public class BoardService {

    // ์†์„ฑ
    private final MemberRepository memberRepository;
    private final BoardRepository boardRepository;

    // ์ƒ์„ฑ์ž
    

    // ๊ธฐ๋Šฅ
    public BoardResponseDto save(String title, String contents, String username) {

        Member findMember = memberRepository.findMemberByUsernameOrElseThrow(username);

        Board board = new Board(title, contents);
        board.setMember(findMember);

        Board savedBoard = boardRepository.save(board);

        return new BoardResponseDto(savedBoard.getId(), savedBoard.getTitle(), savedBoard.getContents());
    }
}

MemberRepository

public interface MemberRepository extends JpaRepository<Member, Long> {

    // ์†์„ฑ

    // ์ƒ์„ฑ์ž

    // ๊ธฐ๋Šฅ
    Optional<Member> findMemberByUsername(String username);
    
    default  Member findMemberByUsernameOrElseThrow(String username) {

        return findMemberByUsername(username).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Does not exist username = " + username));
    }
}

BoardRepository

public interface BoardRepository extends JpaRepository<Board, Long> {
}

8. ๊ฒŒ์‹œ๊ธ€ ์ „์ฒด ์กฐํšŒ ๊ธฐ๋Šฅ

๋”๋ณด๊ธฐ

๊ฒŒ์‹œ๊ธ€ ์ „์ฒด ์กฐํšŒ API ๊ตฌํ˜„

BoardResponseDto

@Getter
public class BoardResponseDto {

    // ์†์„ฑ
    private final Long id;

    private final String title;

    private final String contents;

    // ์ƒ์„ฑ์ž
    public BoardResponseDto(Long id, String title, String contents) {
        this.id = id;
        this.title = title;
        this.contents = contents;
    }

    // ๊ธฐ๋Šฅ
    public static BoardResponseDto toDo(Board board) {
        return new BoardResponseDto(board.getId(), board.getTitle(), board.getContents());
    }
}

BoardController

@RestController
@RequestMapping("/boards")
@RequiredArgsConstructor
public class BoardController {

    // ์†์„ฑ
    private final BoardService boardService;

    // ์ƒ์„ฑ์ž

    // ๊ธฐ๋Šฅ
    @GetMapping
    public ResponseEntity<List<BoardResponseDto>> findAll() {

        List<BoardResponseDto> boardResponseDtoList = boardService.findAll();

        return new ResponseEntity<>(boardResponseDtoList, HttpStatus.OK);
    }
}

BoardService

@Service
@RequiredArgsConstructor
public class BoardService {

    // ์†์„ฑ
    private final MemberRepository memberRepository;
    private final BoardRepository boardRepository;

    // ์ƒ์„ฑ์ž


    // ๊ธฐ๋Šฅ
    public List<BoardResponseDto> findAll() {

        return boardRepository.findAll()
                .stream()
                .map(BoardResponseDto::toDo)
                .toList();
    }
}

9. ํŠน์ • ๊ฒŒ์‹œ๊ธ€ ์กฐํšŒ ๊ธฐ๋Šฅ

๋”๋ณด๊ธฐ

ํŠน์ • Board ์กฐํšŒ API ๊ตฌํ˜„

  • ์š”๊ตฌ์กฐ๊ฑด : ์‘๋‹ต์— ์ž‘์„ฑ์ž ๋‚˜์ด๋ฅผ ํฌํ•จํ•œ๋‹ค.

BoardWithAgeResponseDto

@Getter
public class BoardWithAgeResponseDto {

    // ์†์„ฑ
    private final String title;

    private final String contents;

    private final Integer age;

    // ์ƒ์„ฑ์ž
    public BoardWithAgeResponseDto(String title, String contents, Integer age) {
        this.title = title;
        this.contents = contents;
        this.age = age;
    }
    
    // ๊ธฐ๋Šฅ
}

BoardController

@RestController
@RequestMapping("/boards")
@RequiredArgsConstructor
public class BoardController {

    // ์†์„ฑ
    private final BoardService boardService;

    // ์ƒ์„ฑ์ž

    // ๊ธฐ๋Šฅ
    @GetMapping("/{id}")
    public ResponseEntity<BoardWithAgeResponseDto> findById(@PathVariable Long id) {

        BoardWithAgeResponseDto boardWithAgeResponseDto = boardService.findById(id);

        return new ResponseEntity<>(boardWithAgeResponseDto, HttpStatus.OK);
    }
}

BoardService

@Service
@RequiredArgsConstructor
public class BoardService {

    // ์†์„ฑ
    private final MemberRepository memberRepository;
    private final BoardRepository boardRepository;

    // ์ƒ์„ฑ์ž


    // ๊ธฐ๋Šฅ
    public BoardWithAgeResponseDto findById(Long id) {

        Board findBoard = boardRepository.findByIdOrElseThrow(id);
        Member writer = findBoard.getMember();

        return new BoardWithAgeResponseDto(findBoard.getTitle(), findBoard.getContents(), writer.getAge());
    }
}

BoardRepository

public interface BoardRepository extends JpaRepository<Board, Long> {

    default Board findByIdOrElseThrow(Long id) {

        return findById(id).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Does not exist id = " + id));
    }
}

10. ํŠน์ • ๊ฒŒ์‹œ๊ธ€ ์‚ญ์ œ ๊ธฐ๋Šฅ

๋”๋ณด๊ธฐ

๊ฒŒ์‹œ๊ธ€ ์‚ญ์ œ API ๊ตฌํ˜„

BoardController

@RestController
@RequestMapping("/boards")
@RequiredArgsConstructor
public class BoardController {

    // ์†์„ฑ
    private final BoardService boardService;

    // ์ƒ์„ฑ์ž

    // ๊ธฐ๋Šฅ
    @DeleteMapping("/{id}")
    public ResponseEntity<Void> delete(@PathVariable Long id) {

        boardService.delete(id);

        return new ResponseEntity<>(HttpStatus.OK);
    }
}

BoardService

@Service
@RequiredArgsConstructor
public class BoardService {

    // ์†์„ฑ
    private final MemberRepository memberRepository;
    private final BoardRepository boardRepository;

    // ์ƒ์„ฑ์ž


    // ๊ธฐ๋Šฅ
    public void delete(Long id) {

        Board findBoard = boardRepository.findByIdOrElseThrow(id);

        boardRepository.delete(findBoard);
    }
}

 

์˜ค๋Š˜ ํ•˜๋ฃจ ์ •๋ฆฌ โœ๏ธ

์˜ค๋Š˜์€ ์˜ค์ „์— ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋ฌธ์ œ Java๋ž‘ SQL ํ•œ๋ฌธ์ œ์”ฉ ํ’€๊ณ  ๋ธ”๋กœ๊ทธ์— ์ •๋ฆฌํ–ˆ๋‹ค. ์˜ค๋žœ๋งŒ์— SQL ๋ฌธ์ œ๋ฅผ ํ’€์—ˆ๋Š”๋ฐ ์ƒ๊ฐ๋ณด๋‹ค ์‰ฝ๊ฒŒ ํ’€๋ ธ๋‹ค! ์™„์ „ ๊นŒ๋จน๊ธฐ ์ „์— ๋‹ค์‹œ ๋ฌธ์ œ๋ฅผ ํ’€๊ธฐ ์‹œ์ž‘ํ•ด์„œ ๋‹คํ–‰์ด๋ผ๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ๋‹ค.

์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋ฌธ์ œ๋ฅผ ๋๋‚ด๊ณ  ๋‚˜์„œ๋Š” ์ญ‰ Spring ์ˆ™๋ จ 3์ฃผ์ฐจ ์‹ค์Šต ๊ฐ•์˜๋ฅผ ๋“ค์—ˆ๋‹ค. ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค๊ณ  JPA๋ฅผ ์‹ค์Šตํ•˜๋Š” ์‹œ๊ฐ„์ด์—ˆ๋Š”๋ฐ ํ™•์‹คํžˆ JDBC๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ํŽธ๋ฆฌํ•œ ๋ฐฉ๋ฒ•์ด๋ผ๋Š” ์ƒ๊ฐ์ด ๋“ค์—ˆ๋‹ค. JPA๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ฝ”๋“œ๊ฐ€ ์—„์ฒญ ๊ฐ„๋‹จํ•ด์กŒ๋‹ค!!!! ๊ทธ๋ž˜์„œ ํฅ๋ฏธ๋กญ๊ฒŒ ๊ฐ•์˜๋ฅผ ๋”ฐ๋ผํ•˜๋ฉด์„œ CRUD ๊ธฐ๋Šฅ์„ ์™„์„ฑํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

๊ทผ๋ฐ ๋ญ”๊ฐ€ ๊ฐ•์˜๋ฅผ ๋‹ค๋“ฃ๊ณ  ๋‚˜๋‹ˆ๊นŒ ์ดํ•ดํ•˜๊ธฐ๋„ ์ „์— ๊ทธ๋ƒฅ ์ฝ”๋“œ๋ฅผ ๋”ฐ๋ผ์น˜๋ฉด์„œ ๊ตฌํ˜„๋งŒ ํ•œ ๋Š๋‚Œ์ด๋ผ์„œ ์ƒˆ๋กœ ํ”„๋กœ์ ํŠธ๋ฅผ ๋งŒ๋“ค๊ณ  ๊ธฐ์–ต์— ์˜์กดํ•˜๋ฉด์„œ ๋‹ค์‹œ ์ง์ ‘ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด๋ดค๋‹ค. ๋ฌผ๋ก  ๋‹ค ๊ธฐ์–ตํ•˜์ง€ ๋ชปํ•ด์„œ ๊ฐ•์˜ ์ž๋ฃŒ๋ฅผ ์ฐธ๊ณ ํ•˜๋ฉด์„œ ์ฝ”๋“œ๋ฅผ ์ดํ•ดํ•˜๊ณ  ํ๋ฆ„์„ ์ดํ•ดํ•˜๋ฉด์„œ ํ•˜๋‹ˆ๊นŒ ํ›จ์”ฌ ๋จธ๋ฆฌ์— ์ž˜ ๋“ค์–ด์˜ค๋Š” ๋Š๋‚Œ์ด ๋“ค์—ˆ๋‹ค. ์‹œ๊ฐ„์€ ๋งŽ์ด ๊ฑธ๋ ธ์ง€๋งŒ ์ง์ ‘ ์ž‘์„ฑํ•œ ์ฝ”๋“œ๊ฐ€ ๋งŽ์œผ๋‹ˆ๊นŒ ๋ฟŒ๋“ฏํ–ˆ๋‹ค ๐Ÿ˜ƒ

์˜ค๋Š˜์€ ๊ฐ•์˜ ์‹ค์Šต ๋”ฐ๋ผํ•˜๊ณ  ๋ณต์Šตํ•œ๋‹ค๊ณ  ํ•˜๋ฃจ๋ฅผ ๋‹ค ์“ด ๊ฒƒ ๊ฐ™๋‹ค. ๋‚ด์ผ๋ถ€ํ„ฐ๋Š” ์ง„์งœ ๊ณผ์ œ๋ฅผ ์‹œ์ž‘ํ•ด์•ผ์ง€..
๊ณผ์ œ๋ฅผ ์ตœ๋Œ€ํ•œ ๋นจ๋ฆฌ ์‹œ์ž‘ํ•ด์„œ ์–ด๋ ค์šด ๋‚ด์šฉ๋“ค์— ์ง์ ‘ ๋ถ€๋”ชํžˆ๋ฉด์„œ ํ•ด๊ฒฐํ•˜๊ณ  ํ•œ์ธต ๋” ์„ฑ์žฅํ•˜๋ฉด ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค! ๋‚ด์ผ๋ถ€ํ„ฐ ๊ณผ์ œ๋ฅผ ์‹œ์ž‘ํ•˜๋ฉด ์ง„์ด ์ญ‰์ญ‰ ๋น ์ง€๊ฒ ์ง€๋งŒ ์ค‘๊ฐ„์ค‘๊ฐ„ ์ž˜ ์‰ฌ์–ด๊ฐ€๋ฉด์„œ ์ง„ํ–‰ํ•˜๋ฉด ๋ฌธ์ œ์—†์„ ๊ฒƒ ๊ฐ™๋‹ค!

์˜ค๋Š˜ ํ•˜๋ฃจ๋„ ์—ด์‹ฌํžˆ ๊ณต๋ถ€ํ–ˆ๊ณ  ๋‚ด์ผ๋งŒ ์ž˜ ๋ณด๋‚ด๋ฉด ๋˜ ์ฃผ๋ง์ด๋‹ˆ๊นŒ ์—ด์‹ฌํžˆ ๊ณต๋ถ€ํ•˜์ž!!! ํŒŒ์ดํŒ…!! 

 

๋‚ด์ผ ๊ณ„ํš โฐ

  • ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋ฌธ์ œ(Java, SQL) 1๋ฌธ์ œ ํ’€์ด & ๋ธ”๋กœ๊ทธ ์ •๋ฆฌ
  • ๊ณผ์ œ ์‹œ์ž‘ํ•ด๋ณด๊ธฐ(?)
  • TIL ๋ธ”๋กœ๊ทธ ์ž‘์„ฑ

+ ์ถ”๊ฐ€๋กœ ๊ณ„ํš์ด ๋” ์ƒ๊ธธ ์ˆ˜๋„ ์žˆ์Šด๋‹ค~_~