Java DataSource, JDBC DataSource 예제

자바 DataSource 및 JDBC DataSource 프로그래밍은 자바 프로그램에서 데이터베이스와 작업하는 방법입니다. 이미 JDBC DriverManager을 사용하여 관계형 데이터베이스 연결을 가져올 수 있는 방법을 살펴 보았습니다. 그러나 실제 프로그래밍에서는 연결 이상의 기능이 필요합니다.

Java DataSource

대부분의 경우 연결을 쉽게 전환할 수 있도록 연결 유연성, 트랜잭션 관리를 위한 연결 풀링 및 분산 시스템 지원을 찾고 있습니다. 응용 프로그램에서 이러한 기능 중 하나를 찾고 있다면 JDBC DataSource가 선호되는 접근 방식입니다. 자바 DataSource 인터페이스는 javax.sql 패키지에 있으며 getConnection()getConnection(String str1,String str2) 두 가지 오버로드된 메서드만 선언합니다.

JDBC DataSource

다양한 데이터베이스 공급 업체는 DataSource 인터페이스의 다양한 종류의 구현을 제공하는 책임이 있습니다. 예를 들어 MySQL JDBC 드라이버는 com.mysql.jdbc.jdbc2.optional.MysqlDataSource 클래스를 사용하여 DataSource 인터페이스의 기본 구현을 제공하고 오라클 데이터베이스 드라이버는 oracle.jdbc.pool.OracleDataSource 클래스를 사용하여 이를 구현합니다. 이러한 구현 클래스는 데이터베이스 서버 세부 정보를 사용자 자격 증명과 함께 제공할 수 있는 방법을 제공합니다. 이러한 JDBC DataSource 구현 클래스가 제공하는 일부 다른 일반적인 기능은 다음과 같습니다;

  • PreparedStatement의 캐싱을 통한 빠른 처리
  • 연결 시간 초과 설정
  • 로그 기능
  • ResultSet 최대 크기 임계값

JDBC DataSource 예제

간단한 JDBC DataSource 예제 프로젝트를 만들고 MySQL 및 Oracle DataSource의 기본 구현 클래스를 사용하여 데이터베이스 연결을 가져오는 방법을 배워보겠습니다. 최종 프로젝트는 아래 이미지와 같을 것입니다.

Java JDBC DataSource – 데이터베이스 설정

예제 프로그램에 들어가기 전에 테이블과 샘플 데이터로 데이터베이스 설정이 필요합니다. MySQL 또는 Oracle 데이터베이스의 설치는 이 튜토리얼의 범위를 벗어나므로, 테이블과 샘플 데이터를 설정하겠습니다.

-- 직원 테이블 생성
CREATE TABLE `Employee` (
  `empId` int(10) unsigned NOT NULL,
  `name` varchar(10) DEFAULT NULL,
  PRIMARY KEY (`empId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- 샘플 데이터 삽입
INSERT INTO `Employee` (`empId`, `name`)
VALUES
	(1, 'Pankaj'),
	(2, 'David');

commit;
CREATE TABLE "EMPLOYEE"
  (
    "EMPID"   NUMBER NOT NULL ENABLE,
    "NAME"    VARCHAR2(10 BYTE) DEFAULT NULL,
    PRIMARY KEY ("EMPID")
  );

Insert into EMPLOYEE (EMPID,NAME) values (10,'Pankaj');
Insert into EMPLOYEE (EMPID,NAME) values (5,'Kumar');
Insert into EMPLOYEE (EMPID,NAME) values (1,'Pankaj');
commit;

이제 자바 프로그램으로 넘어갑니다. 데이터베이스 구성을 느슨하게 결합하기 위해 속성 파일에서 읽겠습니다. db.properties 파일:

# MySQL DB 속성
MYSQL_DB_DRIVER_CLASS=com.mysql.jdbc.Driver
MYSQL_DB_URL=jdbc:mysql://localhost:3306/UserDB
MYSQL_DB_USERNAME=pankaj
MYSQL_DB_PASSWORD=pankaj123

# Oracle DB 속성
ORACLE_DB_DRIVER_CLASS=oracle.jdbc.driver.OracleDriver
ORACLE_DB_URL=jdbc:oracle:thin:@localhost:1521:orcl
ORACLE_DB_USERNAME=hr
ORACLE_DB_PASSWORD=oracle

위의 구성이 로컬 설정과 일치하는지 확인하세요. 또한 프로젝트의 빌드 경로에 MySQL 및 Oracle DB JDBC jar 파일이 포함되어 있는지 확인하세요.

Java JDBC DataSource – MySQL, Oracle 예제

MySQL 또는 Oracle DataSource를 가져오는 데 사용할 수 있는 팩토리 클래스를 작성해 보겠습니다.

package com.journaldev.jdbc.datasource;

import java.io.FileInputStream;
import java.io.IOException;
import java.sql.SQLException;
import java.util.Properties;

import javax.sql.DataSource;

import oracle.jdbc.pool.OracleDataSource;

import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;

public class MyDataSourceFactory {

	public static DataSource getMySQLDataSource() {
		Properties props = new Properties();
		FileInputStream fis = null;
		MysqlDataSource mysqlDS = null;
		try {
			fis = new FileInputStream("db.properties");
			props.load(fis);
			mysqlDS = new MysqlDataSource();
			mysqlDS.setURL(props.getProperty("MYSQL_DB_URL"));
			mysqlDS.setUser(props.getProperty("MYSQL_DB_USERNAME"));
			mysqlDS.setPassword(props.getProperty("MYSQL_DB_PASSWORD"));
		} catch (IOException e) {
			e.printStackTrace();
		}
		return mysqlDS;
	}
	
	public static DataSource getOracleDataSource(){
		Properties props = new Properties();
		FileInputStream fis = null;
		OracleDataSource oracleDS = null;
		try {
			fis = new FileInputStream("db.properties");
			props.load(fis);
			oracleDS = new OracleDataSource();
			oracleDS.setURL(props.getProperty("ORACLE_DB_URL"));
			oracleDS.setUser(props.getProperty("ORACLE_DB_USERNAME"));
			oracleDS.setPassword(props.getProperty("ORACLE_DB_PASSWORD"));
		} catch (IOException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return oracleDS;
	}
		
}

Oracle과 MySQL DataSource 구현 클래스가 매우 유사하다는 점에 유의하십시오. 이러한 메서드를 사용하고 몇 가지 테스트를 실행하는 간단한 테스트 프로그램을 작성해 보겠습니다.

package com.journaldev.jdbc.datasource;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import javax.sql.DataSource;

public class DataSourceTest {

	public static void main(String[] args) {
		
		testDataSource("mysql");
		System.out.println("**********");
		testDataSource("oracle");

	}

	private static void testDataSource(String dbType) {
		DataSource ds = null;
		if("mysql".equals(dbType)){
			ds = MyDataSourceFactory.getMySQLDataSource();
		}else if("oracle".equals(dbType)){
			ds = MyDataSourceFactory.getOracleDataSource();
		}else{
			System.out.println("invalid db type");
			return;
		}
		
		Connection con = null;
		Statement stmt = null;
		ResultSet rs = null;
		try {
			con = ds.getConnection();
			stmt = con.createStatement();
			rs = stmt.executeQuery("select empid, name from Employee");
			while(rs.next()){
				System.out.println("Employee ID="+rs.getInt("empid")+", Name="+rs.getString("name"));
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}finally{
				try {
					if(rs != null) rs.close();
					if(stmt != null) stmt.close();
					if(con != null) con.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
		}
	}

}

클라이언트 클래스가 데이터베이스별 클래스와 완전히 독립되어 있음을 알아두세요. 이는 클라이언트 프로그램에서 기밀성을 유지하고 느슨한 결합 및 추상화 이점을 얻을 수 있도록 하며, 클라이언트 프로그램에서 기밀성을 유지하고 추상화 이점을 얻을 수 있도록 합니다. 위의 테스트 프로그램을 실행하면 아래와 같은 출력을 얻을 수 있습니다.

Employee ID=1, Name=Pankaj
Employee ID=2, Name=David
**********
Employee ID=10, Name=Pankaj
Employee ID=5, Name=Kumar
Employee ID=1, Name=Pankaj

Apache Commons DBCP 예시

위의 Java DataSource 팩토리 클래스를 살펴보면 크게 두 가지 문제가 있습니다.

  1. MySQL 및 Oracle DataSource를 생성하기 위한 팩토리 클래스 메서드는 각각의 드라이버 API와 강하게 결합되어 있습니다. Oracle 데이터베이스 지원을 향후 제거하거나 다른 데이터베이스 지원을 추가하려면 코드 변경이 필요합니다.
  2. MySQL 및 Oracle DataSource를 가져오기 위한 대부분의 코드는 유사하며, 유일한 차이점은 사용하는 구현 클래스입니다.

Apache Commons DBCP API는 프로그램과 다양한 JDBC 드라이버 간의 추상화 레이어로 작동하는 Java DataSource 구현을 제공함으로써 이러한 문제를 해결할 수 있습니다. Apache DBCP 라이브러리는 Commons Pool 라이브러리에 의존하므로 이미지에 표시된 대로 빌드 경로에 두어야 합니다. 여기에는 DataSource의 간단한 구현인 BasicDataSource를 사용하는 DataSource 팩토리 클래스가 있습니다.

package com.journaldev.jdbc.datasource;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.commons.dbcp.BasicDataSource;

public class DBCPDataSourceFactory {

	public static DataSource getDataSource(String dbType){
		Properties props = new Properties();
		FileInputStream fis = null;
		BasicDataSource ds = new BasicDataSource();
		
		try {
			fis = new FileInputStream("db.properties");
			props.load(fis);
		}catch(IOException e){
			e.printStackTrace();
			return null;
		}
		if("mysql".equals(dbType)){
			ds.setDriverClassName(props.getProperty("MYSQL_DB_DRIVER_CLASS"));
            ds.setUrl(props.getProperty("MYSQL_DB_URL"));
            ds.setUsername(props.getProperty("MYSQL_DB_USERNAME"));
            ds.setPassword(props.getProperty("MYSQL_DB_PASSWORD"));
		}else if("oracle".equals(dbType)){
			ds.setDriverClassName(props.getProperty("ORACLE_DB_DRIVER_CLASS"));
            ds.setUrl(props.getProperty("ORACLE_DB_URL"));
            ds.setUsername(props.getProperty("ORACLE_DB_USERNAME"));
            ds.setPassword(props.getProperty("ORACLE_DB_PASSWORD"));
		}else{
			return null;
		}
		
		return ds;
	}
}

사용자 입력에 따라 MySQL 또는 Oracle DataSource가 생성됩니다. 응용 프로그램에서 하나의 데이터베이스만 지원하는 경우 이러한 논리가 필요하지 않습니다. 속성을 변경하면 다른 데이터베이스 서버로 전환할 수 있습니다. Apache DBCP가 추상화를 제공하는 핵심 포인트는 setDriverClassName() 메서드입니다. 다음은 위의 팩토리 메서드를 사용하여 다양한 유형의 연결을 가져오는 클라이언트 프로그램입니다.

package com.journaldev.jdbc.datasource;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import javax.sql.DataSource;

public class ApacheCommonsDBCPTest {

	public static void main(String[] args) {
		testDBCPDataSource("mysql");
		System.out.println("**********");
		testDBCPDataSource("oracle");
	}

	private static void testDBCPDataSource(String dbType) {
		DataSource ds = DBCPDataSourceFactory.getDataSource(dbType);
		
		Connection con = null;
		Statement stmt = null;
		ResultSet rs = null;
		try {
			con = ds.getConnection();
			stmt = con.createStatement();
			rs = stmt.executeQuery("select empid, name from Employee");
			while(rs.next()){
				System.out.println("Employee ID="+rs.getInt("empid")+", Name="+rs.getString("name"));
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}finally{
				try {
					if(rs != null) rs.close();
					if(stmt != null) stmt.close();
					if(con != null) con.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
		}
	}

}

위의 프로그램을 실행하면 출력이 이전 프로그램과 동일합니다. Java JDBC DataSource와 위의 사용법을 살펴보면 일반 DriverManager로도 수행할 수 있습니다. Java DataSource의 주요 이점은 컨텍스트와 JNDI 내에서 사용될 때 나타납니다. 간단한 구성으로 컨테이너 자체에서 유지되는 데이터베이스 연결 풀을 만들 수 있습니다. 대부분의 서블릿 컨테이너(예: 톰캣 및 JBoss)는 자체 Java DataSource 구현을 제공하며 간단한 XML 기반 구성을 통해 구성한 다음 JNDI 컨텍스트 조회를 사용하여 Java DataSource를 가져와 사용할 수 있습니다. 이를 통해 응용 프로그램 측에서 서버 측으로 연결 풀링과 관리를 처리하여 응용 프로그램의 비즈니스 로직을 작성하는 데 더 많은 시간을 할애할 수 있습니다. 다음 튜토리얼에서는 Tomcat 컨테이너에서 DataSource를 구성하고 웹 응용 프로그램에서 사용하는 방법을 배워보겠습니다.

Source:
https://www.digitalocean.com/community/tutorials/java-datasource-jdbc-datasource-example