Loading...
Spring Framework Reference Documentation 7.0.2의 Initializing a DataSource의 한국어 번역본입니다.
아래의 경우에 피드백에서 신고해주신다면 반영하겠습니다.
감사합니다 :)
DataSourceorg.springframework.jdbc.datasource.init package는 기존 DataSource를 초기화하기 위한 지원을 제공합니다. Embedded database 지원은 애플리케이션을 위한 DataSource를 생성하고 초기화하는 하나의 옵션을 제공합니다.
그러나 서버 어딘가에서 동작하는 인스턴스를 초기화해야 하는 경우가 있을 수 있습니다.
데이터베이스를 초기화하고 DataSource 빈에 대한 레퍼런스를 제공할 수 있는 경우 spring-jdbc 네임스페이스에서 initialize-database 태그를 사용할 수 있습니다:
1<jdbc:initialize-database data-source="dataSource"> 2 <jdbc:script location="classpath:com/foo/sql/db-schema.sql"/> 3 <jdbc:script location="classpath:com/foo/sql/db-test-data.sql"/> 4</jdbc:initialize-database>
위 예제는 지정된 두 스크립트를 데이터베이스에 대해 실행합니다. 첫 번째 스크립트는 스키마를 생성하고, 두 번째 스크립트는 테이블을 테스트 데이터 세트로 채웁니다.
스크립트 위치는 Spring에서 리소스에 사용되는 일반적인 Ant 스타일의 와일드카드가 포함된 패턴일 수도 있습니다(예:
classpath*:/com/foo/**/sql/*-data.sql). 패턴을 사용하면 스크립트는 URL 또는 파일 이름의 렉시컬 순서로 실행됩니다.
데이터베이스 이니셜라이저의 기본 동작은 제공된 스크립트를 조건 없이 실행하는 것입니다. 이는 스크립트를 이미 테스트 데이터가 들어 있는 데이터베이스에 대해 실행하는 경우처럼 항상 원하는 동작이 아닐 수 있습니다.
데이터를 실수로 삭제할 가능성은 (앞에서 보여준) 일반적인 패턴을 따라 테이블을 먼저 생성하고 그 다음 데이터를 insert함으로써 줄일 수 있습니다. 테이블이 이미 존재하는 경우 첫 번째 단계에서 실패합니다.
그러나 기존 데이터의 생성 및 삭제를 보다 세밀하게 제어하기 위해 XML 네임스페이스는 몇 가지 추가 옵션을 제공합니다. 첫 번째는 초기화를 켜고 끄기 위한 플래그입니다. 이는 환경에 따라 설정할 수 있습니다(예: 시스템 프로퍼티나 environment 빈에서 불리언 값을 가져옴).
다음 예제는 시스템 프로퍼티에서 값을 가져옵니다:
1<jdbc:initialize-database data-source="dataSource" 2 enabled="#{systemProperties.INITIALIZE_DATABASE}"> 3 <jdbc:script location="..."/> 4</jdbc:initialize-database>
| 1 | INITIALIZE_DATABASE라는 시스템 프로퍼티에서 enabled 값을 가져옵니다. |
기존 데이터에서 발생하는 일을 제어하기 위한 두 번째 옵션은 실패에 대해 좀 더 관대해지는 것입니다. 이를 위해 이니셜라이저가 스크립트에서 실행하는 SQL의 특정 에러를 무시하는 기능을 제어할 수 있습니다.
다음 예제가 이를 보여줍니다:
1<jdbc:initialize-database data-source="dataSource" ignore-failures="DROPS"> 2 <jdbc:script location="..."/> 3</jdbc:initialize-database>
위 예제에서 우리는 때때로 스크립트가 비어 있는 데이터베이스에 대해 실행되며, 따라서 스크립트에 있는 일부 DROP statement가 실패할 것이라고 예상하고 있습니다. 따라서 실패한 SQL DROP statement는 무시되지만, 다른 실패는 예외를 발생시킵니다.
이는 SQL dialect가 DROP … IF EXISTS(또는 이와 유사한 것)를 지원하지 않지만 재생성하기 전에 모든 테스트 데이터를 조건 없이 제거하고자 할 때 유용합니다. 이 경우 첫 번째 스크립트는 일반적으로 DROP statement의 집합이고, 그 다음에 CREATE statement의 집합이 옵니다.
ignore-failures 옵션은 NONE(기본값), DROPS(실패한 drop을 무시), ALL(모든 실패를 무시)로 설정할 수 있습니다.
각 statement는 스크립트에 ; 문자가 전혀 존재하지 않는 경우 ; 또는 새 줄로 구분해야 합니다.
다음 예제에서 보듯이 이는 전역적으로 또는 스크립트별로 제어할 수 있습니다:
1<jdbc:initialize-database data-source="dataSource" separator="@@"> 2 <jdbc:script location="classpath:com/myapp/sql/db-schema.sql" separator=";"/> 3 <jdbc:script location="classpath:com/myapp/sql/db-test-data-1.sql"/> 4 <jdbc:script location="classpath:com/myapp/sql/db-test-data-2.sql"/> 5</jdbc:initialize-database>
| 1 | 스크립트의 separator를 @@로 설정합니다. |
| 2 | db-schema.sql의 separator를 ;로 설정합니다. |
이 예제에서 두 개의 test-data 스크립트는 statement separator로 @@를 사용하고, 오직 db-schema.sql만 ;를 사용합니다. 이 설정은 기본 separator가 @@이며 db-schema 스크립트에 대해서만 해당 기본값을 override한다고 지정합니다.
XML 네임스페이스에서 제공하는 것보다 더 많은 제어가 필요한 경우 DataSourceInitializer를 직접 사용하고 이를 애플리케이션의 컴포넌트로 정의할 수 있습니다.
큰 범주의 애플리케이션(Spring 컨텍스트가 시작된 이후까지 데이터베이스를 사용하지 않는 애플리케이션)은 추가적인 복잡성 없이 데이터베이스 이니셜라이저를 사용할 수 있습니다.
애플리케이션이 이러한 범주에 속하지 않는다면 이 절의 나머지 부분을 읽어야 할 수 있습니다.
데이터베이스 이니셜라이저는 DataSource 인스턴스에 의존하며 초기화 콜백에서 제공된 스크립트를 실행합니다(XML 빈 정의의 init-method, 컴포넌트의 @PostConstruct 메서드 또는 InitializingBean을 구현하는 컴포넌트의 afterPropertiesSet() 메서드와 유사). 다른 빈이 동일한 데이터 소스에 의존하고 초기화 콜백에서 데이터 소스를 사용하는 경우 데이터가 아직 초기화되지 않았기 때문에 문제가 발생할 수 있습니다.
이에 대한 일반적인 예는 캐시가 eager하게 초기화되고 애플리케이션 시작 시 데이터베이스에서 데이터를 로드하는 경우입니다.
이 문제를 해결하기 위해 두 가지 옵션이 있습니다: 캐시 초기화 전략을 더 나중 phase로 변경하거나 데이터베이스 이니셜라이저가 먼저 초기화되도록 보장하는 것입니다.
애플리케이션이 여러분의 통제 하에 있는 경우에는 캐시 초기화 전략을 변경하는 것이 쉬울 수 있지만, 그렇지 않은 경우에는 쉽지 않을 수 있습니다.
이를 구현하는 방법에 대한 몇 가지 제안은 다음과 같습니다:
Lifecycle 또는 SmartLifecycle을 구현하도록 합니다. 애플리케이션 컨텍스트가 시작될 때 autoStartup 플래그를 설정하여 SmartLifecycle을 자동으로 시작할 수 있으며, 둘러싸고 있는 컨텍스트에서 ConfigurableApplicationContext.start()를 호출하여 Lifecycle을 수동으로 시작할 수 있습니다.ApplicationEvent 또는 유사한 커스텀 observer mechanism을 사용하여 캐시 초기화를 trigger합니다. ContextRefreshedEvent는 컨텍스트가 사용 준비가 되었을 때(모든 빈이 초기화된 후) 항상 컨텍스트에 의해 publish되므로, 이는 종종 유용한 hook입니다(SmartLifecycle이 기본적으로 동작하는 방식).데이터베이스 이니셜라이저가 먼저 초기화되도록 보장하는 것도 쉬울 수 있습니다.
이를 구현하는 방법에 대한 몇 가지 제안은 다음과 같습니다:
BeanFactory의 기본 동작에 의존합니다. 기본 동작은 빈이 registration order로 초기화된다는 것입니다. XML 설정에서 애플리케이션 모듈을 순서대로 나열하는 <import/> element 집합의 일반적인 관행을 채택하고 데이터베이스와 데이터베이스 초기화가 먼저 나열되도록 함으로써 쉽게 이를 구성할 수 있습니다.DataSource와 이를 사용하는 비즈니스 컴포넌트를 분리하고, 이를 별도의 ApplicationContext 인스턴스에 배치하여 startup 순서를 제어합니다(예: parent 컨텍스트에는 DataSource가 있고 child 컨텍스트에는 비즈니스 컴포넌트가 포함되는 구조). 이 구조는 Spring 웹 애플리케이션에서 일반적이지만 보다 일반적으로 적용될 수 있습니다.Embedded Database Support
Data Access with R2DBC