스프링 부트는 자동으로 내장 데이터베이스를 생성한다
build.gradle에 스프링 부트에 내장된 H2, HSQL,Derby 데이터베이스 의존성을 추가하면 자동으로 데이터베이스를 구성할 수 있다.
근데 만약 클래스 경로에 여러 내장 데이터베이스가 존재한다면 spring.datasource.embadded-database-connection 을 이용하여 어떤 데이터베이스를 사용할 것인지 선택할 수 있다. 만약 none으로 한다면 내장 데이터베이스 자동설정은 비활성화 된다
또한 spring.datasource.url 과 같이 특정 url 이 없다면 내장 데이터 베이스를 자동으로 생성한다
그렇다면 url 즉 내장 데이터베이스의 주소는 어떻게 되는 걸까??
무작위로 결정된다
@SuppressWarnings("deprecation")
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@ConditionalOnMissingBean(type = "io.r2dbc.spi.ConnectionFactory")
@AutoConfigureBefore(SqlInitializationAutoConfiguration.class)
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({ DataSourcePoolMetadataProvidersConfiguration.class,
DataSourceInitializationConfiguration.InitializationSpecificCredentialsDataSourceInitializationConfiguration.class,
DataSourceInitializationConfiguration.SharedCredentialsDataSourceInitializationConfiguration.class })
public class DataSourceAutoConfiguration {
@Configuration(proxyBeanMethods = false)
@Conditional(EmbeddedDatabaseCondition.class)
@ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
@Import(EmbeddedDataSourceConfiguration.class)
protected static class EmbeddedDatabaseConfiguration {
}
...
}
여기서 이부분을 보면 해당 빈들을 못찾는 경우 EmbeddedDataSourceConfiguration을 바탕으로 빈을 등록한다
@ConditionalOnMissingBean({ DataSource.class, XADataSource.class }) @Import(EmbeddedDataSourceConfiguration.class)
그래서 EmbeddedDataSourceConfiguration 코드를 보면
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(DataSourceProperties.class)
public class EmbeddedDataSourceConfiguration implements BeanClassLoaderAware {
private ClassLoader classLoader;
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
@Bean(destroyMethod = "shutdown")
public EmbeddedDatabase dataSource(DataSourceProperties properties) {
return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseConnection.get(this.classLoader).getType())
.setName(properties.determineDatabaseName()).build();
}
}
dataSource의 메서드를 보면 DataSourceProperties가 주입되는데 이를 통해 데이터베이스의 이름이 결정된다
@ConfigurationProperties(prefix = "spring.datasource")
public class DataSourceProperties implements BeanClassLoaderAware, InitializingBean {
...
public String determineDatabaseName() {
if (this.generateUniqueName) {
if (this.uniqueName == null) {
this.uniqueName = UUID.randomUUID().toString();
}
return this.uniqueName;
}
if (StringUtils.hasLength(this.name)) {
return this.name;
}
if (this.embeddedDatabaseConnection != EmbeddedDatabaseConnection.NONE) {
return "testdb";
}
return null;
}
...
}
코드를 보면 null 이면 UUID를 통해 무작위로 이름을 설정한다
그래서 결과적으로는 스프링부트가 올라갈때마다 새로운 이름의 데이터베이스가 생성된다. 만약 여러개의 SpringBootTest를 한번에 올리더라도 데이터베이스를 공유하는 문제는 생기지 않는다
스프링부트 sql 파일 자동으로 읽어오다
스프링 부트는 schema.sql 이나 data.sql에서 SQL을 로드한다
다만 주의할점은 schema.sql파일에 create table 명령만 있을 경우 테이블이 이미 데이터베이스에 존재한다면 오류가 발생할 것이다
그래서 drop table을 파일 상단에 해주는 것이 오류를 방지할 수 있다
schema.sql
- 주로 DDL 작성
- DDL : 데이터베이스 계정, 스키마, 테이블, 인데스, 제약사항등 데이터베이스 구조를 정의할때 사용
data.sql
- 주로 DML 작성
- DML : insert,update, delete 등 데이터 조작하는데 사용
또한 내장형 인메모리 데이터 베이스가 아니고 다른 데이터 베이스를 사용하는 상황에서는 스크립트를 이용해 데이터베이스를 초기화하려면
application.properteis 파일
spring.sql.init.mode = always, embedded, never
를 설정해야한다
- embedded : 인메모리 가 사용될때만 데이터 베이스 초기화 실행
- always : 인메모리 아닌 다른 실제 데이터베이스 사용시 데이터 베이스 초기화 하려면 always 사용
테스트시 @AutoConfigureTestDatabase
테스트에 위의 어노테이션을 붙여주면 property로 설정한 데이터베이스가 아닌 내장 데이터 베이스를 사용하도록 강제할 수있다
다만 이 어노테이션을 사용한다면 application.properties에 설정한 mode 설정은 적용되지 않는다
@DataJdbcTest나 @DataJpaTest는 @AutoConfigureTestDatabase를 포함하기 때문에 기본으로 내장 데이터베이스르 사용한다
'개발 이론 > Spring' 카테고리의 다른 글
[Spring] flyway - BaseJavaMigration? (0) | 2023.11.13 |
---|---|
[Spring] flyway?? DB 마이그레이션?? (1) | 2023.11.13 |
[Spring] @ModelAttribute와 @RequestBody에 대해 (1) | 2023.11.09 |
[Spring] SpringBoot 테스트에 테스트용 데이터베이스 연결 (0) | 2023.11.07 |
[Spring]org.passy 사용하여 @Password validation (0) | 2023.11.07 |