개발소설

Spring Data JDBC 본문

Spring Framework

Spring Data JDBC

ChaeHing 2023. 4. 19. 01:14

JDBC(Java Database Connectivity) 

  • Java 기반 애플리케이션의 코드 레벨에서 사용하는 데이터를 데이터베이스에 저장 및 업데이트하거나 반대로 데이터베이스에 저장된 데이터를 Java 코드 레벨에서 사용할 수 있도록 해주는 Java에서 제공하는 표준 API이다.

 

JDBC의 동작흐름

  • JAVA 애플리케이션 -> JDBC API -> JDBC 드라이버 -> 데이터 베이스
  • Java 애플리케이션에서 JDBC API를 이용해 적절한 데이터베이스 드라이버를 로딩한 후, 데이터베이스와 인터랙션 한다

 

JDBC API 사용 흐름

  1. JDBC 드라이버 로딩
  2. Connection 객체 생성
  3. Statement 객체 생성
  4. Query 실행
  5. ResultSet 객체로부터 데이터 조회
  6. ResultSet 객체 Close,
  7. Statement 객체 Close
  8. Connection 객체 Close

 

  • JDBC의 구체적인 API 사용법을 알 필요는 없지만 JDBC의 동작 흐름을 알면 Spring에서 지원하는 데이터 액세스 기술을 사용하는데 도움이 된다.
  • 데이터베이스 Connection 객체를 미리 만들어서 보관하고 애플리케이션이 필요할 때 이 Connection을 제공해 주는 역할을 하는 Connection 관리자를 바로 Connection Pool이라고 한다.
  • Spring Boot 2.0부터 HikariCP가 기본 DBCP로 채택되었다.

 

데이터 액세스 기술

  • SQL 중심 : mybatis, Spring JDBC 등
  • Object 중심 : JPA, Spring Data JDBC
    • 객체(Object)중심 기술을 ORM(Object-Relational Mapping)

 

Spring Data JDBC 실습

 

의존 라이브러리 추가

  • 인메모리 DB인 H2 사용
dependencies {
..
implementation 'org.springframework.boot:spring-boot-starter-data-jdbc'
runtimeOnly 'com.h2database:h2'
}

 

application.yml 파일에 H2 Browser 활성화 설정

spring:
  h2:
    console:
      enabled: true
      path: /h2  #(1)
  datasource:
    url: jdbc:h2:mem:test  #(2) 
  sql:
    init:
      schema-locations: classpath*:db/h2/schema.sql #(3)
  • (1) : path 
    • localhost:8080/h2
  • (2) : JDBC URL
  • (3): table schema 파일 (.sql)

 

shema.sql

CREATE TABLE IF NOT EXISTS MESSAGE (
    message_id bigint NOT NULL AUTO_INCREMENT,
    message varchar(100) NOT NULL,
    PRIMARY KEY (message_id)
);

 

브라우저로 접속 확인

  • localhost:8080/h2
  • JDBC URL의 (2) 입력
  • Connect 클릭

 

MessagePostDto

package com.codestates.hello_world;

import lombok.Getter;

import javax.validation.constraints.NotBlank;

@Getter
public class MessagePostDto {
    @NotBlank
    private String message;
}

MessageResponseDto

package com.codestates.hello_world;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class MessageResponseDto {
    private long messageId;
    private String message;
}

MessageController

@RequestMapping("/v1/messages")
@RestController
public class MessageController {
    private final MessageService messageService;
    private final MessageMapper mapper;

    public MessageController(MessageService messageService,
                             MessageMapper mapper) {
        this.messageService = messageService;
        this.mapper = mapper;
    }

    @PostMapping
    public ResponseEntity postMessage(
            @Valid @RequestBody MessagePostDto messagePostDto) {
        Message message =
               messageService.createMessage(mapper.messageDtoToMessage(messagePostDto));

        return ResponseEntity.ok(mapper.messageToMessageResponseDto(message));
    }
}

MessageMapper

package com.codestates.hello_world;

import org.mapstruct.Mapper;

@Mapper(componentModel = "spring")
public interface MessageMapper {
    Message messageDtoToMessage(MessagePostDto messagePostDto);
    MessageResponseDto messageToMessageResponseDto(Message message);
}

MessageRepository

package com.codestates.hello_world;

import org.springframework.data.repository.CrudRepository;

public interface MessageRepository extends CrudRepository<Message, Long> {

}
  • 데이터 액세스 계층에서 데이터 베이스와 연동을 담당
  • CurdRepository를 상속
    • CrudRepository는 데이터베이스에 CRUD(데이터 생성, 조회, 수정, 삭제) 작업을 진행하기 위해 Spring에서 지원해 주는 인터페이스
    • <Message, Long> 으로 제네릭타입 설정시
      • Message 엔티티 클래스 객체에 담긴 데이터를 데이터베이스 테이블에 생성, 수정
      • 조회한 데이터를 Message 엔티티 클래스로 변환
      • Long은 Message 엔티티 클래스의 식별자 필드의 데이터 타입 
        • @Id가 붙은 필드의 데이터 타입

Message

  • 엔티티 클래스
package com.codestates.hello_world;

import lombok.Getter;
import lombok.Setter;
import org.springframework.data.annotation.Id;

@Getter
@Setter
public class Message {

    @Id
    private long messageId;
    private String message;
}
  • 클래스명이 데이터 베이스의 테이블 명의 매핑
  • 각각의 멤버 변수(필드)는 데이터베이스 테이블의 필드(컬럼)의 매핑
  • @Id는 고유 식별자 역할 - 데이터베이스의 PK

MessageService

package com.codestates.hello_world;

import org.springframework.stereotype.Service;

@Service
public class MessageService {

    private final MessageRepository messageRepository;

    public MessageService(MessageRepository messageRepository){
        this.messageRepository = messageRepository;
    }

    public Message createMessage(Message message){
        return messageRepository.save(message); // (1)
    }

}
  • MessageRepository를 멤버로 선언하여 생성자 주입 (DI)
  • (1) CurdRepository의 save() 메서드를 사용
    • CrudRepository 인터페이스는 CRUD에 대한 기본적인 메서드를 정의하고 있기 때문에 별도의 CRUD 기능을 개발자가 직접 구현할 필요가 없다.

 

POST 요청시 데이터베이스의 생성되는지 확인

  • localhost:8080/h2
  • SELECT * FROM MESSAGE

 

Comments