[Spring Boot]MySQL+JPA CRUD해보기

한상욱·2023년 11월 6일
0

Spring Boot

목록 보기
7/19
post-thumbnail

들어가며

이 글은 Spring Boot를 공부하며 정리한 글입니다.

MySQL CRUD

이전글들을 통해서 H2+JPA를 이용한 CRUD와 MySQL 연동까지 해봤습니다. 이번에는 MySQL+JPA를 이용한 CRUD입니다. 하지만 이전에는 CRUD만 해보았지만, 이번에는 DTO라는 개념까지 도입해보겠습니다.

이미지 출처 : https://e-una.tistory.com/72

아, 원래는 자료들은 한땀한땀 손으로 만들었었는데, 시간이 부족해서 이번에는 다른분의 개발블로그의 이미지를 첨부했습니다.

DTO

DTO는 Data Transfer Object의 약자로 데이터를 전달해주는 객체입니다. Client와 각 요소들 사이의 데이터를 주고받을 때 담는 그릇같은 역활을 합니다.

우리가 만들 예제는 사람의 정보를 CRUD하는 예제입니다. 따라서, DTO 역시 사람의 정보를 전달하게끔 만들어줄것입니다. 다음은 각각 응답과 요청에 해당하는 DTO입니다.

data class HumanCreateRequestDto (
    val id : Int,
    val name : String,
)

fun HumanCreateRequestDto.toEntity() = Human(
    id = id,
    name = name,
)
data class HumanResponseDto (
    var id : Int,
    var name : String,
)

fun Human.toResponse() = HumanResponseDto (
    id = id,
    name = name,
)
data class HumanUpdateRequestDto (
    var name : String,
)

fun HumanUpdateRequestDto.toEntity(id : Int) = Human(
    id = id,
    name = name,
)

Entity

Entity는 테이블과 1대1로 맵핑되는 객체라고 할 수 있습니다. DB에서 Human이라는 테이블에 접근하기 위해서는 Human Entity를 이용하는 것이죠.

import jakarta.persistence.Entity
import jakarta.persistence.GeneratedValue
import jakarta.persistence.GenerationType
import jakarta.persistence.Id

@Entity
class Human (
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    var id : Int,
    var name : String,
)

Repository

Entity가 DB에 접근하기 위해서는 Repository를 이용합니다. Repository는 interface로 만들어주세요.

import com.example.mysqlpratice.human.entity.Human
import org.springframework.data.repository.CrudRepository

interface HumanRepository : CrudRepository<Human, Int>

Service

Service는 Controller에서 수행하는 실질적인 비즈니스 로직입니다. DB접근을 위해 Repository를 이용합니다.

@Service
class HumanService {

    @Autowired
    private lateinit var humanRepository : HumanRepository
    fun getHumans() : ResponseEntity<List<HumanResponseDto>> {
        val humans = humanRepository.findAll()
        return ResponseEntity(humans.map { it.toResponse() }, HttpStatus.OK)
    }

    fun postHuman(humanCreateDto : HumanCreateRequestDto): ResponseEntity<HumanResponseDto> {
        val human = humanRepository.save(humanCreateDto.toEntity())
        return ResponseEntity(human.toResponse(), HttpStatus.CREATED)
    }

    fun putHuman(id : Int, humanUpdateRequestDto : HumanUpdateRequestDto) : ResponseEntity<HumanResponseDto> {
        humanRepository.findById(id).orElseThrow { ResponseStatusException(HttpStatus.NOT_FOUND) }
        val human = humanRepository.save(humanUpdateRequestDto.toEntity(id))
        return ResponseEntity(human.toResponse(), HttpStatus.OK)
    }

    fun deleteHuman(id : Int) {
        return humanRepository.deleteById(id)
    }
}

@Service 어노테이션은 해당 class가 Service임을 명시합니다.

Controller

드디어 마지막인 Controller 생성입니다. Controller와 Service와 DTO를 이용해서 데이터를 주고받습니다.

@RestController
@RequestMapping("/human")
class HumanController {

    @Autowired
    private lateinit var humanService : HumanService

    @GetMapping
    fun getHumans() : ResponseEntity<List<HumanResponseDto>> =
        humanService.getHumans()

    @PostMapping
    fun postHuman(
        @RequestBody humanCreateRequestDto: HumanCreateRequestDto
    ) : ResponseEntity<HumanResponseDto> = 
        humanService.postHuman(humanCreateRequestDto)

    @PutMapping("/{id}")
    fun putHuman(
        @PathVariable id : Int, 
        @RequestBody humanUpdateRequestDto: HumanUpdateRequestDto
    ) : ResponseEntity<HumanResponseDto> = 
        humanService.putHuman(id, humanUpdateRequestDto)

    @DeleteMapping("/{id}")
    fun deleteHuman(@PathVariable id : Int) = humanService.deleteHuman(id)
}

비즈니스로직이 분리되어 굉장히 깔끔한 구조로 나타납니다. 결과는 생략하도록 하겠습니다.

profile
자기주도적, 지속 성장하는 모바일앱 개발자가 되기 위해

0개의 댓글