Java DataSource、JDBC DataSource の例

JavaのDataSourceとJDBC DataSourceプログラミングは、Javaプログラムでデータベースと連携する方法です。既に確認したように、JDBC DriverManagerを使用してリレーショナルデータベースへの接続を取得できます。ただし、実際のプログラミングでは、接続以上の機能が必要です。

Java DataSource

多くの場合、我々は柔軟な接続、データベースの切り替え容易性、トランザクション管理のためのコネクションプーリング、および分散システムサポートを求めています。JDBC DataSourceは、これらの機能をアプリケーションで利用する場合の推奨される方法です。Java DataSourceインターフェースは、javax.sqlパッケージに存在し、getConnection()およびgetConnection(String str1,String str2)の2つのオーバーロードされたメソッドのみが宣言されています。

JDBC DataSource

異なるデータベースベンダーがDataSourceインタフェースのさまざまな実装を提供する責任があります。たとえば、MySQL JDBCドライバーは、com.mysql.jdbc.jdbc2.optional.MysqlDataSourceクラスを使用してDataSourceインタフェースの基本実装を提供し、Oracleデータベースドライバーは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;

さて、Javaプログラムに移りましょう。データベースの構成を疎結合にするために、プロパティファイルから読み取ります。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は、これらの問題を解決するためにJava DataSourceの実装を提供し、プログラムと異なるJDBCドライバーとの間に抽象化レイヤーとして機能します。Apache DBCPライブラリはCommons Poolライブラリに依存しているため、画像に示されているようにビルドパスに両方があることを確認してください。こちらは、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が作成されることがわかります。アプリケーションで1つのデータベースのみをサポートする場合は、これらのロジックは不要です。プロパティを変更するだけで、データベースサーバーを切り替えることができます。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で使用される場合です。簡単な構成で、コンテナ自体によって維持されるデータベース接続プールを作成できます。ほとんどのサーブレットコンテナ(TomcatやJBossなど)は、独自のJava DataSource実装を提供し、簡単なXMLベースの構成を介してそれを構成し、JNDIコンテキストルックアップを使用してJava DataSourceを取得してそれと共に動作します。これにより、アプリケーション側からサーバー側への接続プールと管理の管理が簡略化され、アプリケーションのビジネスロジックの記述により多くの時間が与えられます。次のチュートリアルでは、TomcatコンテナでDataSourceをどのように構成し、Webアプリケーションで使用できるかを学びます。

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