Loading...
Spring Framework Reference Documentation 7.0.2의 Controlling Database Connections의 한국어 번역본입니다.
아래의 경우에 피드백에서 신고해주신다면 반영하겠습니다.
감사합니다 :)
This section covers:
DataSourceDataSourceUtilsSmartDataSourceAbstractDataSourceSingleConnectionDataSourceDriverManagerDataSourceTransactionAwareDataSourceProxyDataSourceTransactionManager / JdbcTransactionManagerDataSourceSpring은 DataSource를 통해 database에 대한 connection을 얻습니다. DataSource는
JDBC specification의 일부이며 일반화된 connection factory입니다. 이는 컨테이너나
프레임워크가 애플리케이션 코드로부터 connection pooling과 트랜잭션 관리 이슈를
숨길 수 있게 해줍니다.
개발자인 여러분은 database에 어떻게 연결하는지에 대한 세부 사항을 알 필요가 없습니다. 이는 데이터소스를 설정하는 administrator의 책임입니다. 여러분은 코드 개발과 테스트를 하면서 두 역할을 모두 수행할 가능성이 높지만, production data source가 어떻게 구성되는지 반드시 알 필요는 없습니다.
Spring의 JDBC layer를 사용할 때, JNDI에서 데이터 소스를 얻을 수도 있고,
third party에서 제공하는 connection pool implementation으로 직접 구성할 수도
있습니다. 전통적인 선택지는 bean-style DataSource class를 사용하는 Apache Commons DBCP와 C3P0입니다.
modern JDBC connection pool의 경우, 대신 builder-style API를 가진 HikariCP를 고려하십시오.
Spring distribution에 포함된
DriverManagerDataSource와SimpleDriverDataSourceclass는 테스트 용도로만 사용해야 합니다! 이 variant들은 pooling을 제공하지 않으며 connection에 대한 요청이 여러 번 발생할 때 성능이 좋지 않습니다.
다음 section에서는 Spring의 DriverManagerDataSource implementation을 사용합니다.
다른 몇 가지 DataSource variant들은 뒤에서 다룹니다.
DriverManagerDataSource를 구성하려면:
DriverManagerDataSource로
connection을 얻습니다.DriverManager가 driver class를 로드할 수 있도록 JDBC driver의 fully qualified
class name을 지정합니다.다음 예제는 DriverManagerDataSource를 구성하는 방법을 보여줍니다:
1@Bean 2DriverManagerDataSource dataSource() { 3 DriverManagerDataSource dataSource = new DriverManagerDataSource(); 4 dataSource.setDriverClassName("org.hsqldb.jdbcDriver"); 5 dataSource.setUrl("jdbc:hsqldb:hsql://localhost:"); 6 dataSource.setUsername("sa"); 7 dataSource.setPassword(""); 8 return dataSource; 9}
Copied!
1@Bean 2fun dataSource() = DriverManagerDataSource().apply { 3 setDriverClassName("org.hsqldb.jdbcDriver") 4 url = "jdbc:hsqldb:hsql://localhost:" 5 username = "sa" 6 password = "" 7}
Copied!
1<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 2 <property name="driverClassName" value="${jdbc.driverClassName}"/> 3 <property name="url" value="${jdbc.url}"/> 4 <property name="username" value="${jdbc.username}"/> 5 <property name="password" value="${jdbc.password}"/> 6</bean> 7 8<context:property-placeholder location="jdbc.properties"/>
Copied!
다음 두 예제는 DBCP와 C3P0에 대한 기본 connectivity와 configuration을 보여줍니다. pooling feature를 제어하는 데 도움이 되는 더 많은 option을 알아보려면, 각 connection pooling implementation의 product documentation을 참조하십시오.
다음 예제는 DBCP configuration을 보여줍니다:
1@Bean(destroyMethod = "close") 2BasicDataSource dataSource() { 3 BasicDataSource dataSource = new BasicDataSource(); 4 dataSource.setDriverClassName("org.hsqldb.jdbcDriver"); 5 dataSource.setUrl("jdbc:hsqldb:hsql://localhost:"); 6 dataSource.setUsername("sa"); 7 dataSource.setPassword(""); 8 return dataSource; 9}
Copied!
1@Bean(destroyMethod = "close") 2fun dataSource() = BasicDataSource().apply { 3 driverClassName = "org.hsqldb.jdbcDriver" 4 url = "jdbc:hsqldb:hsql://localhost:" 5 username = "sa" 6 password = "" 7}
Copied!
1<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close"> 2 <property name="driverClassName" value="${jdbc.driverClassName}"/> 3 <property name="url" value="${jdbc.url}"/> 4 <property name="username" value="${jdbc.username}"/> 5 <property name="password" value="${jdbc.password}"/> 6</bean> 7 8<context:property-placeholder location="jdbc.properties"/>
Copied!
다음 예제는 C3P0 configuration을 보여줍니다:
1@Bean(destroyMethod = "close") 2ComboPooledDataSource dataSource() throws PropertyVetoException { 3 ComboPooledDataSource dataSource = new ComboPooledDataSource(); 4 dataSource.setDriverClass("org.hsqldb.jdbcDriver"); 5 dataSource.setJdbcUrl("jdbc:hsqldb:hsql://localhost:"); 6 dataSource.setUser("sa"); 7 dataSource.setPassword(""); 8 return dataSource; 9}
Copied!
1@Bean(destroyMethod = "close") 2fun dataSource() = ComboPooledDataSource().apply { 3 driverClass = "org.hsqldb.jdbcDriver" 4 jdbcUrl = "jdbc:hsqldb:hsql://localhost:" 5 user = "sa" 6 password = "" 7}
Copied!
1<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> 2 <property name="driverClass" value="${jdbc.driverClassName}"/> 3 <property name="jdbcUrl" value="${jdbc.url}"/> 4 <property name="user" value="${jdbc.username}"/> 5 <property name="password" value="${jdbc.password}"/> 6</bean> 7 8<context:property-placeholder location="jdbc.properties"/>
Copied!
DataSourceUtilsDataSourceUtils class는 JNDI에서 connection을 얻고 필요할 경우 connection을
close하는 static method를 제공하는 편리하고 강력한 helper class입니다.
이는 thread-bound JDBC Connection을 DataSourceTransactionManager와 함께
지원할 뿐만 아니라 JtaTransactionManager와 JpaTransactionManager와도
함께 지원합니다.
JdbcTemplate은 DataSourceUtils connection access를 내포하고 있으며,
모든 JDBC operation 뒤에서 이를 사용하여, 진행 중인 트랜잭션에 암시적으로
참여한다는 점에 유의하십시오.
SmartDataSourceSmartDataSource interface는 relational database에 대한 connection을 제공할 수 있는
class에 의해 구현되어야 합니다. 이는 DataSource interface를 확장하여,
해당 interface를 사용하는 class가 주어진 operation 이후에 connection을 close해야
하는지 여부를 query할 수 있게 해줍니다.
connection을 재사용해야 한다는 것을 알고 있을 때 이러한 사용 방식은 효율적입니다.
AbstractDataSourceAbstractDataSource는 Spring의 DataSource
implementation을 위한 abstract base class입니다. 이는 모든 DataSource implementation에
공통적인 code를 구현합니다.
자체 DataSource
implementation을 작성하는 경우 AbstractDataSource class를 확장해야 합니다.
SingleConnectionDataSourceSingleConnectionDataSource class는 SmartDataSource
interface의 implementation으로, 각 사용 후에 close되지 않는 단일 Connection을
wrap합니다.
이는 multi-threading이 불가능합니다.
어떤 client code가 (persistence tool을 사용할 때와 같이) pooled connection이라고
가정하고 close를 호출하는 경우, suppressClose property를 true로 설정해야
합니다. 이 설정은 physical connection을 wrap하는 close-suppressing proxy를
반환합니다.
이 경우 더 이상 이를 native Oracle Connection 또는 유사한 객체로
cast할 수 없다는 점에 유의하십시오.
SingleConnectionDataSource는 주로 test class입니다. 이는 일반적으로 간단한
JNDI environment와 함께 애플리케이션 서버 외부의 코드를 쉽게 테스트할 수 있게
해줍니다.
DriverManagerDataSource와 달리, 항상 동일한 connection을 재사용하여
physical connection의 과도한 생성을 피합니다.
DriverManagerDataSourceDriverManagerDataSource class는 bean property를 통해 plain JDBC driver를 구성하고
매번 새로운 Connection을 반환하는 표준 DataSource
interface의 implementation입니다.
이 implementation은 Spring IoC 컨테이너에서 DataSource bean으로 또는 간단한
JNDI environment와 함께 Jakarta EE 컨테이너 외부의 테스트 및 독립 실행형
environment에 유용합니다. pool을 가정하는 Connection.close() 호출은
connection을 close하므로, 어떤 DataSource-aware persistence code도 동작해야
합니다.
그러나 JavaBean-style connection pool(commons-dbcp와 같은)을 사용하는 것은
테스트 environment에서도 매우 쉽기 때문에, 거의 항상 이러한 connection pool을
DriverManagerDataSource보다 사용하는 것이 더 바람직합니다.
TransactionAwareDataSourceProxyTransactionAwareDataSourceProxy는 target DataSource에 대한 proxy입니다. 이 proxy는
해당 target DataSource를 wrap하여 Spring에서 관리하는 트랜잭션에 대한 인식을
추가합니다. 이러한 점에서 이는 Jakarta EE 서버에서 제공하는 transactional JNDI
DataSource와 유사합니다.
이 class를 사용하는 것은, 이미 존재하는 코드를 호출해야 하고 그 코드에 표준 JDBC
DataSourceinterface implementation을 전달해야 하는 경우를 제외하고는 거의 바람직하지 않습니다. 이 경우에도 여전히 이 코드를 사용할 수 있으며, 동시에 이 코드가 Spring에서 관리하는 트랜잭션에 참여하도록 할 수 있습니다. 일반적으로는 리소스 관리를 위한 상위 level abstraction인JdbcTemplate또는DataSourceUtils를 사용하여 새로운 코드를 작성하는 것이 더 바람직합니다.
자세한 내용은
TransactionAwareDataSourceProxy
javadoc을 참조하십시오.
DataSourceTransactionManager / JdbcTransactionManagerDataSourceTransactionManager class는 단일 JDBC DataSource에 대한
PlatformTransactionManager implementation입니다. 이는 지정된 DataSource에서 JDBC Connection을
현재 실행 중인 thread에 binding하여, DataSource당 하나의 thread-bound Connection을
허용할 수 있습니다.
Application code는 Java EE의 표준
DataSource.getConnection 대신
DataSourceUtils.getConnection(DataSource)를 통해 JDBC Connection을
검색해야 합니다. 이는 checked SQLExceptions 대신 unchecked
org.springframework.dao exception을 throw합니다.
모든 프레임워크 class(JdbcTemplate과 같은)는
내부적으로 이 strategy를 사용합니다. 트랜잭션 manager와 함께 사용되지 않는 경우,
lookup strategy는 DataSource.getConnection과 정확히 동일하게 동작하므로 어떤 경우에도
사용할 수 있습니다.
DataSourceTransactionManager class는 savepoint(PROPAGATION_NESTED),
custom isolation level, 그리고 적절한 JDBC statement query timeout으로 적용되는
timeout을 지원합니다. 후자를 지원하려면, 애플리케이션 코드는 JdbcTemplate을
사용하거나 각 statement를 생성할 때마다
DataSourceUtils.applyTransactionTimeout(..) method를 호출해야 합니다.
단일 resource인 경우에는 JTA 트랜잭션 coordinator를 컨테이너가 지원할 필요가
없으므로, JtaTransactionManager 대신 DataSourceTransactionManager를 사용할 수
있습니다. 이러한 트랜잭션 manager 간 전환은 필요한 connection lookup pattern을
지키는 한 configuration만의 문제입니다.
JTA는 savepoint나 custom isolation level을 지원하지 않으며 timeout mechanism이 다르지만, 그 외에는 JDBC resource 및 JDBC commit/rollback 관리 측면에서 유사한 동작을 노출한다는 점에 유의하십시오.
JTA-style의 실제 resource connection lazy retrieval을 위해, Spring은 target connection pool을
위한 해당 DataSource proxy class를 제공합니다:
LazyConnectionDataSourceProxy를
참조하십시오.
이는 실제 statement execution이 없는 잠재적으로 비어 있는 트랜잭션(이러한
시나리오에서는 실제 resource를 전혀 가져오지 않음)에 특히 유용하며, 또한
routing DataSource 앞에서 사용되어 트랜잭션-synchronized read-only flag 및/또는
isolation level을 고려하도록 할 수 있습니다(예: IsolationLevelDataSourceRouter).
LazyConnectionDataSourceProxy는 또한 read-only 트랜잭션 동안 사용할 read-only connection
pool에 대한 특별한 지원을 제공하여, primary connection pool에서 connection을
가져올 때마다(이는 JDBC driver에 따라 비용이 많이 들 수 있습니다) 트랜잭션
시작과 종료 시마다 JDBC Connection의 read-only flag를 전환하는 overhead를
피할 수 있게 해줍니다.
5.3부터 Spring은 commit/rollback 시 exception translation 기능을 추가한 확장
JdbcTransactionManagervariant를 제공합니다(JdbcTemplate과 정렬됨).DataSourceTransactionManager는(이는 JTA와 유사하게) 항상TransactionSystemException만 throw하는 반면,JdbcTransactionManager는 database locking failure 등을 해당하는DataAccessExceptionsubclass로 변환합니다. 애플리케이션 코드는 이러한 exception에 대비해야 하며,TransactionSystemException만을 예상해서는 안 된다는 점에 유의하십시오. 그러한 시나리오에서는JdbcTransactionManager가 권장되는 선택입니다.
Exception behavior 측면에서, JdbcTransactionManager는 대략적으로
JpaTransactionManager 및 R2dbcTransactionManager와 동등하며, 서로에 대한 즉각적인
companion/대체재 역할을 합니다. 반면 DataSourceTransactionManager는
JtaTransactionManager와 동등하며, 그에 대한 직접적인 대체재 역할을 할 수 있습니다.
Using the JDBC Core Classes to Control Basic JDBC Processing and Error Handling
JDBC Batch Operations