28. SQL 데이터베이스 작업 by sh

Spring Framework는 SQL 데이터베이스 작업을 광범위하게 지원합니다. JdbcTemplate을 사용하는 직접 JDBC 액세스부터 Hibernate와 같은 완전한 '객체 관계형 매핑'기술까지. Spring Data는 인터페이스로부터 직접 Repository 구현을 생성하고 컨벤션을 사용하여 메서드 이름에서 쿼리를 생성하는 추가 수준의 기능을 제공합니다.

28.1 DataSource 구성

Java의 javax.sql.DataSource인터페이스는 데이터베이스 연결을 작업하는 표준 방법을 제공합니다. 일반적으로 DataSource는 URL을 사용하여 일부 자격 증명을 사용해서 데이터베이스 연결을 설정합니다.

JAVA의 DataSource 인터페이스

순수 jdbc로 데이터베이스에 접근을 하면, 데이터베이스에 접근할 때마다 connection을 맺고 끊는 작업을 한다. 이 connection을 맺고 끊는 작업을 줄이기 위해 미리 connection을 생성해 두고, 데이터베이스에 접근하고자 하는 사용자에게 미리 생성된 connection을 제공하고 돌려받는다. 이 connection들을 모아두는 장소를 connection pool이라 하며, Datasource는 java 에서 connection pool을 지원하기 위한 인터페이스이다.

28.1.1 내장형 데이터베이스 지원

메모리 내장형 데이터베이스를 사용하여 응용 프로그램을 개발하는 경우에 종종 편리합니다. 분명히 메모리 내 데이터베이스는 영구 저장소를 제공하지 않습니다. 응용 프로그램이 시작될 때 데이터베이스를 채워야하고 응용 프로그램이 종료 될 때 데이터를 버릴 준비가 필요합니다.

스프링 부트는 내장된 H2, HSQLDerby 데이터베이스를 자동 구성 할 수 있습니다. 연결 URL을 제공할 필요가 없으며 사용하려는 내장 데이터베이스에 빌드 종속성을 포함하기만 하면됩니다.

H2 / HSQL(Hyper SQL) / 아파치 더비 데이터베이스

  • 자바로 작성된 관계형 데이터베이스 시스템

예를 들어, 일반적인 POM 종속성은 다음과 같습니다.

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
    <groupId>org.hsqldb</groupId>
    <artifactId>hsqldb</artifactId>
    <scope>runtime</scope>
</dependency>

28.1.2 프로덕션 데이터베이스 연결

프로덕션 데이터베이스 연결은 풀링 DataSource를 사용하여 자동 구성 될 수도 있습니다. 특정 구현을 선택하기위한 알고리즘은 다음과 같습니다.

  • Tomcat이 성능과 동시성을 위해 DataSource를 풀링하는 것을 선호하므로, 가능하다면 항상 그것을 선택합니다.

  • HikariCP를 사용할 수 있다면 사용할 것입니다.

  • Commons DBCP를 사용할 수 있다면 이를 사용할 것이지만 프로덕션 환경에서는 권장하지 않습니다.

  • 마지막으로, Commons DBCP2를 사용할 수 있다면 사용할 것입니다.

HikariCP

빠른 속도로 인해 주목받고 있는 커넥션 풀! 스프링 부트 2.0 에서부터 기본이 되는 JDBC 커넥션 풀.

Commons DBCP

아파치의 오픈 소스 커넥션 풀.

spring-boot-starter-jdbc또는 spring-boot-starter-data-jpa 'starter POMs'를 사용하면 자동으로 tomcat-jdbc에 종속됩니다.

DataSource 구성은 spring.datasource.*의 외부 구성 등록 정보에 의해 제어됩니다. 예를 들어, application.properties에 다음 섹션을 선언 할 수 있습니다.

spring.datasource.url=jdbc:mysql://localhost/test
spring.datasource.username=dbuser
spring.datasource.password=dbpass
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

지원되는 옵션에 대한 자세한 내용은 DataSourceProperties를 참조하십시오. spring.datasource.*:를 통해 DataSource 구현 특정 속성을 구성 할 수 있습니다. 자세한 내용은 사용중인 연결 풀 구현 문서를 참조하십시오.

28.1.3 JNDI DataSource 연결

Spring Boot 애플리케이션을 Application Server에 배포하는 경우 Application Server 내장 기능을 사용하여 DataSource를 구성 및 관리하고 JNDI를 사용하여 액세스 할 수 있습니다.

spring.datasource.jndi-name 속성은 spring.datasource.url, spring.datasource.usernamespring.datasource.password속성의 대안으로 사용되어 특정 JNDI 위치에서 DataSource에 액세스 할 수 있습니다. 예를 들어 application.properties의 다음 섹션에서는 JBoss AS에 정의 된 DataSource에 액세스하는 방법을 보여줍니다.

spring.datasource.jndi-name=java:jboss/datasources/customers

JNDI (Java Naming and Directory Interface) Naming Service

DB의 정보는 Java code에 직접 하드코딩하면 불편한 점이 많다.(유지보수 어려움) 즉, 계정정보와 같은 DB 정보가 바뀐다면 수정하고 재 컴파일하여 서버에 업로드해야 하기 떄문.

DB 정보를 외부(was)에서 관리하고 Source에서는 외부정보를 가져다쓸 수 있는 이름 값을 사용하면 편리하다. 이를 위한 방법이 JNDI이다.

  1. 사용자가 요청을 보낸다.

  2. JNDI에 등록된 DB 정보 객체(DataSource 타입)를 검색한다.

  3. JNDI를 통해 찾은 정보 객체로부터 커넥션을 획득한다.

  4. DB 조작 작업이 끝난 후 획득한 커넥션을 반환한다.

네이밍 서비스는 분산된 환경에서 특정한 이름으로 객체를 등록하고 관리할 수 있는 방법을 의미한다. 객체를 네이밍 서비스에 등록, 삭제 검색할 수 있는 방법을 제공하는 것이 JNDI !

28.2 JdbcTemplate 사용

Spring의 JdbcTemplate 클래스와 NamedParameterJdbcTemplate 클래스는 자동으로 구성되므로 직접 자신의 bean에 @Autowire를 넣을 수 있습니다.

JdbcTemplate

  • 스프링의 가장 기본적인 JDBC 템플릿으로, 색인된 파라미터 기반의 쿼리를 통해 데이터베이스를 쉽게 액세스하는 기능을 제공한다.

    • 모든 JdbcTemplate는 DataSource가 있어야 작동한다.

(사용 법 참고 사이트) https://gmlwjd9405.github.io/2018/12/19/jdbctemplate-usage.html

NamedParameterJdbcTemplate

  • SQL과 값들을 색인된 파라미터 대신 명명된 파라미터로 바인딩해서 쿼리를 수행할 수 있게 해주는 JDBC 템플릿 클래스.

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

@Component
public class MyBean {

    private final JdbcTemplate jdbcTemplate;

    @Autowired
    public MyBean(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    // ...

}

28.3 JPA와 'Spring Data'

Java Persistence API는 객체를 관계형 데이터베이스에 '매핑'할 수있는 표준 기술입니다. spring-boot-starter-data-jpaPOM은 빠른 시작 방법을 제공합니다. 다음과 같은 주요 종속성을 제공합니다.

  • Hibernate - 가장 많이 사용되는 JPA 구현물 중 하나.

  • Spring Data JPA - JPA 기반 리포지토리를 쉽게 구현할 수 있습니다.

  • Spring ORMs - Spring Framework의 핵심 ORM 지원.

JPA

  • 자바 어플리케이션에서 관계형 데이터베이스를 사용하는 방식을 정의한 인터페이스.

    • JAP의 핵심이 되는 EntityManager는 javax.persistence.EntityManager라는 파일에 인터페이스로 정의되어 있다.

Hibernate

  • JPA라는 명세의 구현체! 즉, 위에서 언급한 javax.persistence.EntityManager와 같은 인터페이스를 직접 구현한 라이브러리임

    • JPA의 핵심인 EntityManagerFactory, EntityManager, EntityTransaction을 Hibernate에서는 각각 SessionFactory, Session, Transaction으로 상속받고 각각 Impl로 구현함

Spring Data JPA

  • 스프링에서 JAP를 쓰기 편하게 만들어놓은 모듈! JPA를 한 단계 추상화시킨 Repository라는 인터페이스를 제공함

    • 즉, Spring Data JPA의 Repository의 구현에서 JPA를 사용한다.

28.3.1 Entity 클래스들

전통적으로 JPA 'Entity'클래스는 persistence.xml 파일에 지정됩니다. Spring Boot에서는 이 파일이 필요 없으며 'Entity Scanning'이 사용됩니다. 기본적으로 기본 구성 클래스 (@EnableAutoConfiguration 또는 @SpringBootApplication으로 주석 된 패키지) 아래의 모든 패키지가 검색됩니다.

@Entity, @Embeddable 또는 @MappedSuperclass로 주석 된 클래스가 고려됩니다. 일반적인 엔티티 클래스는 다음과 같습니다.

package com.example.myapp.domain;

import java.io.Serializable;
import javax.persistence.*;

@Entity
public class City implements Serializable {

    @Id
    @GeneratedValue
    private Long id;

    @Column(nullable = false)
    private String name;

    @Column(nullable = false)
    private String state;

    // ... additional members, often include @OneToMany mappings

    protected City() {
        // no-args constructor required by JPA spec
        // this one is protected since it shouldn't be used directly
    }

    public City(String name, String state) {
        this.name = name;
        this.country = country;
    }

    public String getName() {
        return this.name;
    }

    public String getState() {
        return this.state;
    }

    // ... etc

}

28.3.2 Spring Data JPA 리포지토리들

스프링 데이터 JPA Repository는 데이터에 액세스하기 위해 정의 할 수있는 인터페이스입니다. JPA 쿼리는 메소드 이름에서 자동으로 작성됩니다. 예를 들어, CityRepository 인터페이스는 findAllByState(String state) 메소드를 선언하여 주어진 상태의 모든 도시를 찾을 수 있습니다.

좀 더 복잡한 쿼리의 경우 Spring Data의 Query annotation을 사용하여 메소드에 주석을 달 수 있습니다.

Spring Data Repository는 대개 Repository 또는 CrudRepository 인터페이스에서 확장됩니다. 자동 구성을 사용하는 경우 기본 구성 클래스 (@EnableAutoConfiguration 또는 @SpringBootApplication으로 주석 된 패키지)가 포함 된 패키지에서 저장소가 검색됩니다.

다음은 일반적인 Spring Data 저장소 입니다.

Repository<T, ID extends Serializable>

  • T : Repository가 관리하는 도메인 타입

  • ID : Repository가 관리하는 엔티티 ID의 타입

참고

CrudRepository Vs. JpaRepository

둘의 차이는 거의 없음. 구분되는 점은 Paging 처리 시 JpaRepository를 사용해야 쉽게 메소드를 제공 받아 편리한 구현 가능

package com.example.myapp.domain;

import org.springframework.data.domain.*;
import org.springframework.data.repository.*;

public interface CityRepository extends Repository<City, Long> {

    Page<City> findAll(Pageable pageable);

    City findByNameAndCountryAllIgnoringCase(String name, String country);

}

28.3.3 JPA 데이터베이스 작성 및 삭제

기본적으로 JPA 데이터베이스는 내장 데이터베이스 (H2, HSQL 또는 Derby)를 사용하는 경우에만 자동으로 작성됩니다. spring.jpa.*속성을 사용하여 JPA 설정을 명시적으로 구성 할 수 있습니다. 예를 들어, 테이블을 작성하고 제거하려면 application.properties에 다음을 추가 할 수 있습니다.

spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.properties.hibernate.globally_quoted_identifiers=true

hibernate.globally_quoted_identifiers를 Hibernate 엔티티 관리자에게 전달합니다.

기본적으로 DDL 실행 (또는 유효성 검사)은 ApplicationContext가 시작될 때까지 연기됩니다. spring.jpa.generate-ddl 플래그도 있지만, ddl-auto 설정이 좀 더 세분화되어 있기 때문에 Hibernate autoconfig가 활성화되어 있다면 사용되지 않습니다.

Last updated