[데브코스] Spring DB Connection

Updated: Categories:

W8D1 - JDBC / MyBatis / JPA 등 스프링에서 DB를 사용하는 방법에 대해 알아보자

JDBC

기본 사용법

  1. JDBC 드라이버 지정
  2. DB 접속 정보를 입력해 Connection 획득
  3. 해당 Connection을 통해 Statement 획득
  4. 쿼리날리기
  5. Connection과 Statement 닫아주기

예시

try{
    Class.forName(드라이버);
    Connection connection = DriverManager.getConnection(DB주소, 유저명, 비번);
    Statement statement = connection.createStatement();
    statement.executeQuery(쿼리);
    statement.close();
    connection.close();
} ...


JDBC Template

  • Spring Boot의 JDBC Template을 통해 커넥션의 과정을 자동화할 수 있다.

기본 사용법

  1. DB 접속 정보(datasource)를 application.yaml에 작성
  2. App Context 생성
  3. @Autowired로 JdbcTemplate 생성

예시

@Autowired
JdbcTemplate jdbcTemplate;
...

jdbcTemplate.update(쿼리)
jdbcTemplate.query(쿼리, resultSet 조작)
jdbcTemplate.queryForObject(쿼리, resultSet 조작)


MyBatis

  • JDBC만 사용하면 자바 코드와 SQL문의 문법을 섞어서 사용해야하는 단점이 존재한다.
  • 따라서 Query Mapper인 MyBatis를 사용하여 코드와 SQL을 분리해보자

기본 사용법

  1. 쿼리를 사용하는 Repository 인터페이스를 작성한다
  2. 해당 인터페이스의 메소드와 매핑되는 mapper xml을 작성한다
  3. 위에서 작성한 인터페이스와 xml을 application.yaml에서 매핑시켜준다

Repository Interface

  • @Mapper 어노테이션으로 컴포넌트 등록
@Mapper
public interface RepositoryInterface {
    메소드1,
    메소드2,
    ...
}

Mapper XML

  • 해당 xml 파일에 쿼리를 작성. (경로는 resources 폴더 하위)
  • mapper의 namespace에 매핑할 인터페이스의 경로를 설정해줘야 한다.
  • 인터페이스의 메소드명과 id가 일치하는 경우 쿼리가 실행됨
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="매핑할 인터페이스 경로">
    <insert id="메소드1">
        쿼리작성
    </insert>
    <select id="메소드2">
        쿼리작성
    </select>
    ...
</mapper>

yaml 설정

  • 도메인 모델을 모아놓은 패키지 경로를 설정하여 매핑 기준을 정해준다
    • 객체 -> 쿼리
    • 쿼리 결과 -> 객체
  • 쿼리를 작성하는 xml 경로를 설정한다.
mybatis:
  # 쿼리결과(Result Set)을 어떤 자바 객체로 매핑할지 지정한다
  type-aliases-package: 도메인 모델 패키지 경로
  configuration:
    map-underscore-to-camel-case: true          # 매핑 객체명은 카멜케이스로
    default-fetch-size: 100                     # 쿼리 레코드 몇개까지 가져올지 설정
    default-statement-timeout: 30               # statement 타임아웃 설정
  mapper-locations: classpath:mapper/*.xml      # 쿼리 xml 경로 지정

사용

  • 구현체가 없는 인터페이스지만, 메소드를 호출하면 Mapper XML을 통해 쿼리가 실행된다
  • 도메인 객체를 입력할 수 있고, 결과값 또한 도메인 객체에 매핑되어 나온다.
@Autowired
RepositoryInterface repositoryInterface;
...

var 도메인객체 = repositoryInterface.메소드1(도메인객체);


JPA

  • 쿼리를 작성하지 않고 자바 코드 entity를 통해 데이터에 접근하는 ORM
  • 자바 객체와 DB 테이블이 완벽히 연동되어 동작한다!
  • SQL 의존적 개발에서 탈피, 객체중심 개발이 가능하다.
  • But 관계형 DB를 중심으로 구조화되어 있기 때문에 OOP의 특징을 지원하지는 않는다.

yaml

  • jpa 설정은 yaml 파일에서~
spring:
  jpa:
    generate-ddl: true
    open-in-view: false
    show-sql: true

Entity

  • @Entity 어노테이션으로 컴포넌트 등록
  • @Table 어노테이션으로 특정 테이블과 entity 클래스를 매핑한다.
    • 생략시 클래스명과 동일한 테이블과 매핑됨
  • @Id 어노테이션으로 PK인 필드를 지정한다.
  • JPA 객체는 default 생성자만을 사용한다
@Entity
@Table(name = "테이블명")
public class CustomerEntity {
    @Id
    private 키값
}

Repository

  • 기존 방식대로라면 Repository에 작성할게 많았지만 JPA를 사용하면 인터페이스만 선언해주면된다. (뭐야이거..)
  • JpaRepository를 상속받기만 하면 끝.
    • 인자값엔 어떤 Entity와 매핑할지와 PK 타입(ex. Long)을 넣어주면 된다.
public interface 레포지토리 extends JpaRepository<엔티티, PK타입> {
}

사용

  • JPA로 매핑된 인터페이스를 사용하기만 하면 된다. (Django에서 모델 사용하는것처럼..)
  • 메소드는 이미 JPA 내부에 정의되어 있음 (findAll, save 등등..)
@Autowired
RepositoryInterface repositoryInterface;
...

var 도메인객체 = repositoryInterface.메소드()

Transactional

  • @Transactional이 붙어 있으면 쿼리결과 객체는 영속성 컨텍스트에서 관리된다
  • 트랜잭션 안에서 쿼리결과 객체의 변화가 감지되면 자동으로 업데이트 쿼리가 실행됨.


JPA 구조

  • JPA는 라이브러리가 아닌 인터페이스, 즉 관계형 DB를 어떻게 자바 객체로 사용할지를 정의한 방법일 뿐이다.
  • Hibernate는 JPA 인터페이스를 구현한 구현체이다.
    • 즉 우리가 가져다 쓸 수 있는 라이브러리임.
  • Spring Data JPA는 JPA를 쓰기 편하게 만들어주는 모듈이다.
    • 우리가 Repository를 통해 JPA를 편하게 사용할 수 있는 것은 Spring Data JPA 내부에 있는 Entity Manager 덕분임

image

출처 : https://suhwan.dev/2019/02/24/jpa-vs-hibernate-vs-spring-data-jpa/