Symfoware

Symfowareについての考察blog

H2 Database EngineにMySQLとのLINKED TABLEを作成する

H2 Database Engineのリファレンスを見ていると、LINKED TABLEという
機能についての解説がありました。

Linked Tables

どうやら、別のデータベースのテーブルを仮想的にH2にあるテーブルのように見せる機能みたいです。
これはおもしろいかも。

MySQLとのLINKED TABLEを作って見ました。






MySQLにデータベースとテーブルの作成



H2からリンクするデータベースとテーブルをMySQLに作成します。

データベースとテーブル、テストデータの投入に使用したクエリは以下のとおり。


CREATE DATABASE linkedtest CHARACTER SET utf8 COLLATE utf8_general_ci;
use linkedtest;
CREATE TABLE T_MYSQL (id integer, val varchar(20));

INSERT INTO T_MYSQL(id, val) value (1, 'mysqlval_1');
INSERT INTO T_MYSQL(id, val) value (2, 'mysqlval_2');
INSERT INTO T_MYSQL(id, val) value (3, 'mysqlval_3');
INSERT INTO T_MYSQL(id, val) value (4, 'mysqlval_4');
INSERT INTO T_MYSQL(id, val) value (5, 'mysqlval_5');
INSERT INTO T_MYSQL(id, val) value (6, 'mysqlval_6');
INSERT INTO T_MYSQL(id, val) value (7, 'mysqlval_7');
INSERT INTO T_MYSQL(id, val) value (8, 'mysqlval_8');
INSERT INTO T_MYSQL(id, val) value (9, 'mysqlval_9');
INSERT INTO T_MYSQL(id, val) value (10, 'mysqlval_10');



linkedtestというデータベースにT_MYSQLというテーブルを作成。
適当にサンプルのデータをインサートしました。







MySQLのJDBCドライバ



LINKED TABLEを使うには、別データベースに接続するためJDBCドライバが必要なようです。
今回はMySQLとLINKED TABLEしてみるので、MySQLのJDBCドライバをダウンロードしました。

http://dev.mysql.com/downloads/connector/j/
ここからmysql-connector-java-5.1.18.tar.gzをダウンロードして解凍し、
mysql-connector-java-5.1.18-bin.jarを取得します。







H2起動時のclasspath指定



H2はDebianで動かしています。
環境はここで作成した時と同様。
DebianでH2 Database Engineを起動し、別端末からJavaで接続する

/opt/h2/binにh2-1.3.162.jarがある状態です。

MySQLのサイトからダウンロードして取得したmysql-connector-java-5.1.18-bin.jarを
/opt/h2/libにコピーしました。

このコピーしたjarをクラスパスに含めて、H2を起動します。
起動するときのオプションはこんな感じ。


# java -cp h2-1.3.162.jar:/opt/h2/lib/mysql-connector-java-5.1.18-bin.jar
    org.h2.tools.Server -webAllowOthers -tcpAllowOthers -baseDir /opt/h2/data


※実際は一行。Windowsの場合は、-cp以降のjarファイルの区切り文字が「;」になるかと思います。


これで準備は完了です。






Javaのサンプルプログラム



別端末からJavaのプログラムで接続してLINKED TABLEを作成し、検索してみます。

なお、LINKED TABLEを作成する時の構文は



CREATE LINKED TABLE [H2内で使用するテーブル名]('[JDBCドライバクラス]', '[接続文字列]', '[ユーザー名]', '[パスワード]', '[リンクするテーブル名]');



そのため、今回MySQLに作成したlinkedtestデータベースのT_MYSQLテーブルを
T_LINKという名称でLINKED TABLEにするには


CREATE LINKED TABLE T_LINK
('com.mysql.jdbc.Driver', 'jdbc:mysql://localhost/linkedtest',
'[MySQLのユーザー名]', '[MySQLのパスワード]', 'T_MYSQL')


となりまkす。


これらを踏まえ、
・MySQLとT_LINKというLINKED TABLEを作成
・H2にT_H2というテーブルを作成
・T_LINK(MySQLのテーブル)とT_H2(H2のテーブル)を結合し、検索結果表示
というサンプルはこんな感じになりました。

※実行するクライアントにMySQLのJDBCドライバは不要です。
H2のJDBCドライバだけあればOK




package com.fc2.blog68.symfoware.h2;

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

public class SampleLinked {
    public static void main(String[] args) throws Exception {
        
        //JDBCドライバをロード
        Class.forName("org.h2.Driver");
        
        //コネクション取得
        Connection conn = DriverManager.getConnection("jdbc:h2:tcp://192.168.1.4/test", "sa", "");
        Statement stmt = conn.createStatement();
        
        //テーブル作成
        stmt.execute("CREATE TABLE IF NOT EXISTS T_H2 (id integer, val varchar(20))");
        stmt.execute("DELETE FROM T_H2");
        
        
        //データの登録
        stmt.execute("INSERT INTO T_H2 (id, val) values (1, 'h2val_1')");
        stmt.execute("INSERT INTO T_H2 (id, val) values (2, 'h2val_2')");
        stmt.execute("INSERT INTO T_H2 (id, val) values (3, 'h2val_3')");
        stmt.execute("INSERT INTO T_H2 (id, val) values (4, 'h2val_4')");
        stmt.execute("INSERT INTO T_H2 (id, val) values (5, 'h2val_5')");
        stmt.execute("INSERT INTO T_H2 (id, val) values (6, 'h2val_6')");
        stmt.execute("INSERT INTO T_H2 (id, val) values (7, 'h2val_7')");
        stmt.execute("INSERT INTO T_H2 (id, val) values (8, 'h2val_8')");
        stmt.execute("INSERT INTO T_H2 (id, val) values (9, 'h2val_9')");
        stmt.execute("INSERT INTO T_H2 (id, val) values (10, 'h2val_10')");
        
        //リンクテーブル作成
        stmt.execute("CREATE LINKED TABLE T_LINK('com.mysql.jdbc.Driver', 'jdbc:mysql://localhost/linkedtest', 'root', 'password', 'T_MYSQL')");
        
        //登録したデータの検索
        StringBuffer sql = new StringBuffer();
        sql.append("SELECT");
        sql.append(" T_H2.id AS H2_ID,");
        sql.append(" T_H2.val AS H2_VAL,");
        sql.append(" T_LINK.id AS MYSQL_ID,");
        sql.append(" T_LINK.val AS MYSQL_VAL");
        sql.append(" FROM");
        sql.append(" T_H2, T_LINK");
        sql.append(" WHERE");
        sql.append(" (T_H2.id = T_LINK.id)");
        
        ResultSet rs = stmt.executeQuery(sql.toString());
        while(rs.next()) {
            System.out.print(rs.getString("H2_ID") + " : ");
            System.out.print(rs.getString("H2_VAL") + " : ");
            System.out.print(rs.getString("MYSQL_ID") + " : ");
            System.out.println(rs.getString("MYSQL_VAL"));
        }
        
        stmt.close();
        conn.close();
        
    }
}






実行してみると、ちゃんとMySQLの表とH2の表の結合結果が表示されます。

1 : h2val_1 : 1 : mysqlval_1
2 : h2val_2 : 2 : mysqlval_2
3 : h2val_3 : 3 : mysqlval_3
4 : h2val_4 : 4 : mysqlval_4
5 : h2val_5 : 5 : mysqlval_5
6 : h2val_6 : 6 : mysqlval_6
7 : h2val_7 : 7 : mysqlval_7
8 : h2val_8 : 8 : mysqlval_8
9 : h2val_9 : 9 : mysqlval_9
10 : h2val_10 : 10 : mysqlval_10






もちろん、

stmt.execute("INSERT INTO T_LINK(id, val) values (11, 'mysqlval_11')");


として、MySQLのテーブルにデータの追加、更新も可能です。

これ、複数のデータベースが混在している環境で上手く使えば、強力な機能かも。


関連記事

テーマ:データベース - ジャンル:コンピュータ

  1. 2011/12/06(火) 23:08:58|
  2. H2 Database Engine
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集
<<javascriptだけで画像にグラデーションをつけるサンプル | ホーム | H2 Database EngineにPythonから接続する(psycopg使用)>>

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック

トラックバック URL
http://symfoware.blog68.fc2.com/tb.php/853-0f3f7df2
この記事にトラックバックする(FC2ブログユーザー)