SpringBoot Document Review 7
https://docs.spring.io/spring-boot/docs/2.1.13.RELEASE/reference/html/
SQL 데이터베이스
https://docs.spring.io/spring-boot/docs/2.1.13.RELEASE/reference/html/boot-features-sql.html
- Spring Framework는 JdbcTemplate과 ORM기술을 제공한다.
- Spring Data는 인터페이스들로부터 직접적으로 Repository 구현체를 만들고, 메소드명으로부터 쿼리로 변환시킬 수 있는 기능을 제공한다.
1. DataSource 설정
- Java의 javax.sql.DataSource 인터페이스는 데이터베이스 연동을 위한 표준 방법을 제공한다.
- 보통, DataSource는 데이터베이스 연결을 구축하기 위해 인증과 함께 URL을 사용한다.
1) 내장 DB에 연결하기
- in-memory DB는 persistent storage를 제공하지는 않는다.
- SpringBoot는 내장 H2, HSQL, Derby DB들을 자동 설정 해주기 때문에, 연결 URL들을 설정하지 않아도 되고 관련 dependency만 추가해주면 된다. 참고로, spring-jdbc가 포함되어 있어야 자동 설정이 이루어지는데, 웬만하면 DB관련 starter들에 포함되어 있다.
- 'spring.datasource.generate-unique-name=true'로 설정하면 각 application context가 하나의 개별 내장 DB를 가질 수 있도록 보장된다.
- 내장 DB의 연결 URL을 설정할 때, DB의 자동 shutdown이 비활성화 되도록 신경써야 한다. 이를 비활성화하면, DB의 종료를 SpringBoot가 DB로의 접근이 더 이상 필요하지 않으면 연결이 종료되도록 제어를 할 수 있게 된다.
※ H2의 경우 : "DB-CLOSE-ON-EXIT=FALSE"
※ HSQLDB의 경우 : "shutdown=true"를 제외할 것
- SpringBoot는 자동으로 DataSource의 스키마를 생성하고 초기화한다. DDL script와 DML script로 각각 root classpath의 schema.sql, data.sql 파일을 참조한다. 만약 platform을 사용한다면 schema-${platform}.sql, data-${platform.sql}.sql 파일을 참조한다. platform 값은 spring.datasource.platform 속성에 지정된 값으로, hsqldb, h2, oracle, mysql, postgresql 등을 지정 가능하다.
2) Production DB에 연결하기
- DataSource를 사용하여 Production DB 연결에 대한 자동 설정이 이루어질 수 있다.
- DataSource의 적용 우선순위는 HikariCP>Tomcat>Commons DBCP2이며, spring-boot-starter-jdbc 혹은 spring-boot-starter-data-jpa를 사용하면 HikariCP dependency가 자동으로 적용된다. 이 우선순위를 우회하기 위해 spring.datasource.type 속성을 지정하는 방법도 있다.
- DataSource Bean을 따로 정의하면 자동 설정은 이루어지지 않는다.
application.properties에서의 DataSource 설정 예시
spring.datasource.url=jdbc:mysql://localhost/test
spring.datasource.username=dbuser
spring.datasource.password=dbpass
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
2. JdbcTemplate 사용하기
- Spring의 JdbcTemplate, NamedParameterJdbcTemplate 클래스는 자동 설정되며, 아래 예시와 같이 이들을 Autowire하여 사용할 수 있다.
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;
}
// ...
}
- spring.jdbc.template.* 속성으로 JdbcTemplate 관련 설정이 가능하다.
- NamedParameterJdbcTemplate는 동일한 JdbcTemplate를 재사용하는 클래스이고, 2개 이상의 JdbcTemplate이 정의되었으면서 primary candidate가 존재하지 않는다면 NamedParameterJdbcTemplate는 자동 설정되지 않는다.
+참고) 여러 DataSource 사용하기
https://2dongdong.tistory.com/33
3. JPA
- JPA(Java Persistence API)는 객체를 Relational DB와 매핑해주는 표준 기술이다.
- spring-boot-starter-data-jpa pom을 추가함으로써 적용되며, Hibernate, Spring Data JPA, Spring ORMs dependency들이 같이 제공된다.
- ORM(Object Relational Mapping) : 객체와 관계형 데이터베이스(RDB)를 매핑시켜주는 프레임워크
- JPA(Java Persistent API) : ORM을 사용하기 위한 인터페이스들을 모아둔 것
- Hibernate : JPA를 구현한 ORM 라이브러리들중 하나
1) Entity Classes
- 보통 JPA Entity 클래스들은 persistence.xml에 명시되어 있지만, SpringBoot에서는 persistence.xml 파일이 필수가 아닌 대신에 Entity Scanning이 사용된다.
- 기본적으로 main configuration 클래스(@EnableAutoConfiguration 혹은 @SpringBootApplication)가 포함되어 있는 모든 패키지들이 스캐닝되고, @Entity, @Embeddable, 혹은 @MappedSuperclass가 붙은 모든 클래스들이 스캐닝된다.
- @EntityScan 어노테이션을 이용하여 Entity를 스캐닝할 위치를 커스터마이징할 수 있다.
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() {
// JPA에서는 argument가 없는 생성자도 필요하다.
// 직접적으로 사용되지 않도록 protected 접근자를 사용한 것이다.
}
public City(String name, String state) {
this.name = name;
this.state = state;
}
public String getName() {
return this.name;
}
public String getState() {
return this.state;
}
// ... etc
}
2) Spring Data JPA Repositories
- Spring Data JPA Repository는 데이터 접근을 위해 정의할 수 있는 인터페이스이다.
- JPA 쿼리들은 메소드명에 의해 자동으로 생성된다. - 예) findAllByState(String state)
- 더 복잡한 JPA 쿼리들의 경우에는, Spring Data의 @Query 어노테이션에 SQL문을 직접 작성해서 메소드에 붙일 수도 있다.
- 자동 설정을 사용한다면, repository들은 메인 configuration 클래스(@EnableAutoConfiguration 또는 @SpringBootApplication)를 포함하는 패키지로부터 스캐닝된다.
- Spring Data repository들은 보통 Repositoy, CrudRepository, 혹은 JpaRepository 클래스를 상속 받는다.
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.Optional;
public interface UserRepository extends JpaRepository<User, Long> {
Optional<User> findByEmail(String email);
}
import org.springframework.data.domain.*;
import org.springframework.data.repository.*;
public interface CityRepository extends Repository<City, Long> {
Page<City> findAll(Pageable pageable);
City findByNameAndStateAllIgnoringCase(String name, String state);
}
※ Spring Data repository 클래스를 상속받는 인터페이스는 자동으로 Bean 등록이 된다.
3) Creating and Dropping JPA Databases
- 기본적으로, JPA 데이터베이스는 내장 데이터베이스(H2, HSQL, Derby)를 사용할 경우에만 자동 생성된다.
- "spring.jpa.*" 속성을 사용하여 명시적으로 JPA 설정을 할 수 있다.
spring.jpa.hibernate.ddl-auto=create-drop
※ 위의 설정에 대한 Hibernate의 내부 속성명은 hibernate.hbm2ddl.auto이며, "spring.jpa.properties.*" 속성을 사용함으로써 다른 Hibernate의 고유의 속성들과 함께 사용할 수 있다.
spring.jpa.properties.hibernate.hbm2ddl.auto=create-drop
- 기본적으로, DDL 실행은 ApplicationContext가 시작될때까지 미뤄진다.
- 자동 설정이 활성화되어 있다면 "spring.jpa.generate-ddl" 속성은 사용되지 않는다.
4) Open EntityManager in View
- Web application을 실행하면 Spring Boot는 기본적으로 Web View에서 lazy loading을 허용하도록 OpenEntityManagerInViewInterceptor를 등록하여 "Open EntityManager in View" 패턴을 적용한다. 이 동작을 원하지 않는다면, application.jpa.open-in-view 속성을 application.properties에서 false로 설정하면 된다.
4. H2의 Web Console 사용하기
- H2 Database는 Spring Boot에 의해 자동 설정된 브라우저 기반 콘솔을 제공해 준다. 웹 애플리케이션(WebFlux 해당 안됨)이고, com.h2database:h2가 classpath에 있고, Spring Boot의 개발툴을 사용해야지만 자동 설정이 이루어진다.
※ Spring Boot의 개발툴을 사용하지 않는 대신에, spring.h2.console.enabled 속성을 true로 설정하는 방법도 있다.
- H2 console을 개발용으로만 사용하는 것이라면, Production 환경에서 spring.h2.console.enabled 속성을 true로 지정하지 않도록 각별한 주의가 필요하다.
- 기본 console 경로는 "/h2-console"인데, "spring.h2.console.path" 속성을 이용하여 console의 경로를 커스터마이징할 수 있다.
5. jOOQ 사용하기
https://www.jooq.org/doc/3.11.12/manual-single-page/#Overview
- jOOQ는 Java Object Oriented Querying의 줄임말로, 데이터베이스로부터 Java 코드를 생성해주는 Data Geekery의 유명 제품이다.
- jOOQ는 type-safe SQL 쿼리들을 API를 통하여 빌드해준다.
- Spring Boot와 함께 상업용과 오픈소스판이 둘다 사용될 수 있다.
1) Code 생성
- jOOQ의 type-safe 쿼리들을 이용하기 위해, 데이터베이스 스키마에 대한 Java 클래스를 미리 생성해야 한다.
- jooq-codegen-maven 플러그인을 사용할 때 spring-boot-starter-parent가 있다면, 플러그인의 <version> 태그를 생략할 수 있다. 추가로, 플러그인의 dependency를 선언하기 위해 "h2.version"과 같은 Spring Boot가 정의하는 버전 변수를 사용할 수도 있다.
- 플러그인 설정 : https://github.com/jOOQ/jOOQ/blob/main/jOOQ-examples/jOOQ-jpa-example/pom.xml (<!-- The jOOQ code generator plugin --> 부분)
※ 위 붉은 상자 부분에는 스캔하려는 여러분의 패키지명을 입력하고, 아래 붉은 상자 부분에는 DB 스키마로부터 생성된 Java 클래스를 생성할 패키지 위치를 입력한다.
2) DSLContext 사용
- DSL은 SQL을 코드로 작성할 수 있도록 하는 빌더 오픈소스 API이다.
- jOOQ가 제공하는 API는 org.jooq.DSLContext 인터페이스를 통해 초기화된다.
- DSLContext는 Spring Bean으로 자동 설정되고, DSLContext를 애플리케이션의 DataSource에 연결한다.
- DSLContext를 사용하기 위해 @Autowired를 사용할 수 있다.
...
@Autowired
DSLContext dsl;
...
dsl.insertInto(USER)
.set(USER.ID, Sequences.HIBERNATE_SEQUENCE.nextval())
.set(USER.NAME, "Jooyeok")
.set(USER.AGE, 24")
.execute();
3) jOOQ SQL Dialect(방언)
- 만약 "spring.jooq.sql-dialect" 속성이 설정되어 있지 않다면, Spring Boot가 datasourse를 위한 SQL Dialect를 직접 판단한다. Dialect를 판단하지 못했을 경우에는 DEFAULT를 반환한다.
※ dialect(방언) : DB로서의 방언은, 같은 동작이라도 DB 종류마다 사용하는 명령어가 다르기 때문에 방언이라고 표현한 것이다. 즉, 해당 DB의 방언으로 소통하기 위해 dialect 설정을 해주는 것이다.
※ jOOQ의 오픈 소스 버전에서 지원해주는 방언만 자동 설정 될 수 있다.
4) jOOQ 커스터마이징
- @Bean을 직접 정의함으로서, 더 개선된 커스터마이징이 가능하다.
- 아래에 있는 jOOQ 종류들에 대한 @Bean을 정의할 수 있다.
- 만약 jOOQ의 설정을 자신이 완전히 제어하고싶다면, org.jooq.Configuration에 @Bean을 추가하여 생성한다.
'Spring Series > Document' 카테고리의 다른 글
[SpringBoot] 공식 문서 요약(9) - RestTemplate, WebClient (0) | 2022.01.08 |
---|---|
[SpringBoot] 공식 문서 요약(8) - NoSQL 기술 (0) | 2021.12.30 |
[SpringBoot] 공식 문서 요약(6) - Security, OAuth2 (0) | 2021.11.27 |
[SpringBoot] 공식 문서 요약(5) - 내장 서블릿 컨테이너 (0) | 2021.11.25 |
[SpringBoot] 공식 문서 요약(4) - Spring WebFlux (0) | 2021.11.15 |
댓글