■ はじめに
https://blogs.yahoo.co.jp/dk521123/37397210.htmlの続き。 今回は、複数DB「sampledb01」「sampledb02」「sampledb03」に アクセスできるようなサンプルを作成する。
補足
* Hibernate であれば、AbstractMultiTenantConnectionProviderが用意されている模様http://docs.jboss.org/hibernate/orm/4.1/devguide/en-US/html/ch16.html
http://useof.org/java-open-source/org.hibernate.engine.jdbc.connections.spi.AbstractMultiTenantConnectionProvider
■ ポイント
* java.sql.Connection.setCatalog(【DB名】)で切り替える[[https://docs.oracle.com/javase/jp/8/docs/api/java/sql/Connection.html#setCatalog-java.lang.String-]]
■ 実行環境
* OS : Windows10 * Java : JDK1.8 * DB : MySQL5.7 * ライブラリは、Gradle を使用してダウンロード。
build.gradle
// Apply the java-library plugin to add support for Java Library apply plugin: 'java-library' // In this section you declare where to find the dependencies of your project repositories { // Use jcenter for resolving your dependencies. // You can declare any Maven/Ivy/file repository here. jcenter() } dependencies { // !! HikariCP for Java8/9 !! compile group: 'com.zaxxer', name: 'HikariCP', version: '2.7.8' testCompile group: 'org.slf4j', name: 'slf4j-simple', version: '1.7.25' // MySQL compile group: 'mysql', name: 'mysql-connector-java', version: '5.1.46' }
■ サンプルDBデータ
-- DB CREATE DATABASE sampledb01; CREATE DATABASE sampledb02; CREATE DATABASE sampledb03; -- Table CREATE TABLE sampledb01.person(id INT NOT NULL AUTO_INCREMENT, name VARCHAR(20), birthdate DATE, PRIMARY KEY (`id`)); CREATE TABLE sampledb02.person(id INT NOT NULL AUTO_INCREMENT, name VARCHAR(20), birthdate DATE, PRIMARY KEY (`id`)); CREATE TABLE sampledb03.person(id INT NOT NULL AUTO_INCREMENT, name VARCHAR(20), birthdate DATE, PRIMARY KEY (`id`)); -- Sample Data INSERT INTO sampledb01.person (`name`, `birthdate`) VALUES ('Mike', '2018-01-01'); INSERT INTO sampledb01.person (`name`, `birthdate`) VALUES ('Tom', '2018-01-02'); INSERT INTO sampledb01.person (`name`, `birthdate`) VALUES ('Kevin', '2018-01-03'); INSERT INTO sampledb02.person (`name`, `birthdate`) VALUES ('Kim', '2018-02-01'); INSERT INTO sampledb02.person (`name`, `birthdate`) VALUES ('Ken', '2018-02-02'); INSERT INTO sampledb02.person (`name`, `birthdate`) VALUES ('Chan', '2018-02-03'); INSERT INTO sampledb03.person (`name`, `birthdate`) VALUES ('Ichiro', '2018-03-01'); INSERT INTO sampledb03.person (`name`, `birthdate`) VALUES ('Giro', '2018-03-02'); INSERT INTO sampledb03.person (`name`, `birthdate`) VALUES ('Taro', '2018-03-03'); INSERT INTO sampledb03.person (`name`, `birthdate`) VALUES ('Saburo', '2018-03-04');
■ サンプル
DbDataSourceManager.java
import java.io.Closeable; import java.sql.Connection; import java.sql.SQLException; import java.text.MessageFormat; import com.zaxxer.hikari.HikariConfig; import com.zaxxer.hikari.HikariDataSource; public class DbDataSourceManager implements Closeable { private static final String DB_URL_FORMAT = "jdbc:mysql://{0}:{1}/{2}?useSSL=false&characterEncoding=UTF-8"; private HikariDataSource dataSource; public DbDataSourceManager() { } public void initialize(String dbHost, String dbPort, String dbName) { HikariConfig dbConfig = DbDataSourceManager.createDbConfig(dbHost, dbPort, dbName); this.dataSource = new HikariDataSource(dbConfig); } public Connection getConnection() throws SQLException { if (this.dataSource == null) { return null; } return this.dataSource.getConnection(); } @Override public void close() { if (this.dataSource != null) { this.dataSource.close(); } } private static HikariConfig createDbConfig(String dbHost, String dbPort, String dbName) { HikariConfig config = new HikariConfig(); // MySQL用ドライバを設定 config.setDriverClassName("com.mysql.jdbc.Driver"); // URL指定 String dbUrl = MessageFormat.format(DB_URL_FORMAT, dbHost, dbPort, dbName); System.out.println("DB URL : " + dbUrl); config.setJdbcUrl(dbUrl); // ユーザ名、パスワード指定 config.addDataSourceProperty("user", "root"); config.addDataSourceProperty("password", "password"); // キャッシュ系の設定(任意) config.addDataSourceProperty("cachePrepStmts", "true"); config.addDataSourceProperty("prepStmtCacheSize", "250"); config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048"); // サーバサイドプリペアードステートメントを使用する(任意) config.addDataSourceProperty("useServerPrepStmts", "true"); // 接続をテストするためのクエリ config.setConnectionInitSql("SELECT 1"); return config; } }
MaltiDbDemo.java
import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class MaltiDbDemo { public static void main(String[] args) { String[] dbNames = new String[] { "sampledb01", "sampledb02", "sampledb03" }; try (DbDataSourceManager dataSourceManager = new DbDataSourceManager();) { dataSourceManager.initialize("localhost", "3306", "sampledb01"); for (String dbName : dbNames) { System.out.println("DB Name : " + dbName); try (Connection connection = dataSourceManager.getConnection();) { // ★ここで切り替え★ connection.setCatalog(dbName); try (Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery("select * from person");) { while (resultSet.next()) { System.out.println("Id:" + resultSet.getString("id") + " Name:" + resultSet.getString("name") + resultSet.getString("birthdate")); } System.out.println("***************"); } catch (SQLException ex) { ex.printStackTrace(); } } catch (SQLException ex) { ex.printStackTrace(); } } } } }出力結果
DB URL : jdbc:mysql://localhost:3306/sampledb01?useSSL=false&characterEncoding=UTF-8 [main] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Starting... [main] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Start completed. DB Name : sampledb01 Id:1 Name:Mike2018-01-01 Id:2 Name:Tom2018-01-02 Id:3 Name:Kevin2018-01-03 *************** DB Name : sampledb02 Id:1 Name:Kim2018-02-01 Id:2 Name:Ken2018-02-02 Id:3 Name:Chan2018-02-03 *************** DB Name : sampledb03 Id:1 Name:Ichiro2018-03-01 Id:2 Name:Giro2018-03-02 Id:3 Name:Taro2018-03-03 Id:4 Name:Saburo2018-03-04 *************** [main] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Shutdown initiated... [main] INFO com.zaxxer.hikari.HikariDataSource - HikariPool-1 - Shutdown completed.