H2 Databaseでauto_incrementの値をJDBCで取得する

H2 Databaseで自動的にインクリメントしてくれる列を作成するには
「auto_increment」を指定してやります。

H2 equivelant of Postgres `SERIAL` or `BIGSERIAL` column?


登録した後、割り当てられた数値の取得方法を調べてみました。


getGeneratedKeys



こちらが参考になります。
6.4 Retrieving AUTO_INCREMENT Column Values through JDBC

サンプルはこのようになりました。


  1. import java.sql.Connection;
  2. import java.sql.ResultSet;
  3. import java.sql.Statement;
  4. public class MainProcess {
  5.     
  6.     public static void main(String... args) throws Exception {
  7.         
  8.         String url = "jdbc:h2:./data/sample";
  9.         Connection con = java.sql.DriverManager.getConnection(url);
  10.         Statement stmt = con.createStatement();
  11.         
  12.         // auto_incrementを指定してテーブルを作成
  13.         stmt.execute("CREATE TABLE IF NOT EXISTS t (id INT auto_increment, val TEXT)");
  14.         
  15.         // 適当に値を登録
  16.         stmt.executeUpdate("INSERT INTO t (val) VALUES ('test value')");
  17.         // getGeneratedKeysで登録した値が取得できる
  18.         ResultSet rs = stmt.getGeneratedKeys();
  19.         if (rs.next()) {
  20.             System.out.println(rs.getInt(1));
  21.         }
  22.         
  23.     }
  24. }




実行するたびに結果で表示される数字が増えていくことがわかります。



【参考URL】

H2 equivelant of Postgres `SERIAL` or `BIGSERIAL` column?
6.4 Retrieving AUTO_INCREMENT Column Values through JDBC

H2SQLのバックアップとリストア

H2SQL、バックアップとリストア用のスクリプトが用意されているとのこと。
Upgrade, Backup, and Restore

こちらで作成した環境で試してみます。
FreeBSD 10.1でH2 Database Engineを起動する


H2SQLの起動



webコンソールを使用したかったので、tcpAllowOthersオプションを指定し
起動しておきました。


# cd /usr/local/opt/h2/bin
# ./h2.sh -webAllowOthers -tcpAllowOthers -baseDir /usr/local/opt/h2/data







バックアップとリストア



バックアップの方法は2種類あるようです。

まず、スクリプトを使用するパターン。


# cd /usr/local/opt/h2/bin
# java -cp h2*.jar org.h2.tools.Script -url jdbc:h2:tcp://192.168.1.103/sample -script sample.zip -options compression zip



sample.zipが出力されました。


以下のコマンドでリストアできます。


# cd /usr/local/opt/h2/bin/
# java -cp h2*.jar org.h2.tools.RunScript -url jdbc:h2:tcp://192.168.1.103/sample -script sample.zip -options compression zip



この方法でバックアップを行った場合、
sqlスクリプトが生成されます。




続いて、SQLで指定する方法。
webコンソールを使用して、


BACKUP TO '/usr/local/opt/h2/backup.zip'



というコマンドを実行します。

621_01.png

621_02.png


この方法のバックアップは、データベースファイル自体がzip圧縮されます。
リストアする場合は、zipファイルを解凍して、
データベースファイルを任意の位置に復元します。

FreeBSD 10.1でH2 Database Engineを起動する

ずいぶん前にDebianでH2 Database Engineを動かしてみました。
DebianでH2 Database Engineを起動し、別端末からJavaで接続する

FreeBSD 10.1で同じことをやってみます。

OpenJDKのインストール



jvmはOpenJDKを使用することにしました。
こちらの手順でインストールしています。
FreeBSD 10.1にOpenJDK 8をインストールする



H2 Databaseの起動



使用するバージョンは現時点(2015/7/5)で最新の1.4.187です。
こちらの、All Platformsのリンクからダウンロード、展開します。
http://www.h2database.com/html/main.html

/usr/local/opt/h2に配置しました。
以前の記事を参考に、

・-tcpAllowOthersで、外部接続許可
・-baseDir /usr/local/opt/h2/dataで、データの保存先を指定

というオプションを指定し、起動します。


# cd /usr/local/opt/h2/bin
# chmod +x h2.sh
# ./h2.sh -tcpAllowOthers -baseDir /usr/local/opt/h2/data
Web Console server running at http://192.168.1.103:8082 (only local connections)
Failed to start a browser to open the URL http://192.168.1.103:8082: Browser detection failed and system property h2.browser not set
TCP server running at tcp://192.168.1.103:9092 (others can connect)
PG server running at pg://192.168.1.103:5435 (only local connections)








外部からの接続



Javaでサンプルを書いてみます。
h2-1.4.187.jarをビルドパスに含めておきます。


  1. package sample;
  2. import java.sql.Connection;
  3. import java.sql.DriverManager;
  4. import java.sql.ResultSet;
  5. import java.sql.Statement;
  6. public class MainProcess {
  7.     
  8.     public static void main(String[] args) throws Exception {
  9.         
  10.         //接続
  11.         String url = "jdbc:h2:tcp://192.168.1.103/sample";
  12.         Connection con = DriverManager.getConnection(url);
  13.         
  14.         Statement stmt = con.createStatement();
  15.         // テーブル作成
  16.         stmt.execute("CREATE TABLE IF NOT EXISTS test (id int, name varchar(10))");
  17.         stmt.execute("INSERT INTO test (id, name) values (1, '日本語テスト')");
  18.         
  19.         ResultSet rs = stmt.executeQuery("SELECT * FROM test");
  20.         
  21.         while(rs.next()) {
  22.             System.out.println(rs.getString("name"));
  23.         }
  24.         rs.close();
  25.         
  26.         stmt.close();
  27.         con.commit();
  28.         con.close();
  29.     }
  30.     
  31. }




実行結果はこちら。


日本語テスト




狙い通り、「/usr/local/opt/h2/data」に「sample.mv.db」という
ファイルが作成されました。

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のテーブルにデータの追加、更新も可能です。

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


H2 Database EngineにPythonから接続する(psycopg使用)

PostgresqlのJDBCドライバを使用して、H2 Database Engineに接続してみました。
H2 Database Engineに、PostgresqlのJDBCドライバでJavaで接続する


ということは、Postgresqlに接続するためのライブラリがあれば
どんな言語からも接続できるはず。

ということで、Pythonからpsycopgを使用して接続してみました。
http://initd.org/psycopg/install/




psycopgのインストール



Ubuntuにpsycopgをインストールします。
まず、ビルドに必要となるライブラリをインストール。


$ sudo apt-get install python-dev libpq-dev




easy_installを使ってインストールするので、setuptoolsをインストール


$ sudo apt-get install python-setuptools




psycopg2をインストール


$ sudo easy_install psycopg2




これでpsycopgのインストールは完了です。







saのパスワード設定



H2 Database Engineに接続するとき、ユーザー「sa」、パスワード空白が
初期値で設定されています。

psycopg2で接続するとき、パスワードに空白を指定すると

Traceback (most recent call last):
    File "sample.py", line 5, in <module>
    con = psycopg2.connect(database="test", user="sa", host = "192.168.1.4", port = 5435, password="")
psycopg2.OperationalError: fe_sendauth: no password supplied


こんな感じで、空白は指定できないというエラーが発生します。


そのため、Webの管理画面からパスワードの設定を行いました。

実行するクエリは以下のとおり。


SET PASSWORD 'Passw0rd'



05_001_20111206214437.png



これで接続しているユーザー(この場合はsaでログインしているのでsa)にパスワードが設定されます。







Pythonのサンプルプログラム



サンプルプログラムはこんな感じになりました。


# -*- coding:utf-8 -*-
import psycopg2
import psycopg2.extras

con = psycopg2.connect(database="test", user="sa", host = "192.168.1.4", port = 5435, password="Passw0rd")
cur = con.cursor(cursor_factory=psycopg2.extras.DictCursor)
cur.execute("SELECT * FROM test")

rec = cur.fetchone()
print rec['name']

cur.close()
con.close()





実行してみると、ちゃんとJavaから登録したデータが得られます。


$ python sample.py
日本語テスト



プロフィール

Author:symfo
blog形式だと探しにくいので、まとめサイト作成中です。
https://symfo.web.fc2.com/

PR

検索フォーム

月別アーカイブ