概要
- H2 Database にてテーブルに主要な JDBC 型となる SQL データ型のカラムを定義して、Java のプログラムからカラムの値を取得するサンプルコードを示す
- 今回の動作確認環境: H2 Database 1.4.200 + Java 14 (AdoptOpenJDK 14.0.2) + Gradle 6.6 + macOS Catalina
JDBC 型とは
JDBC 型は SQL 型と Java 言語の型の間を取り持つ型。SQL のデータを表す型 (CHAR や INTEGER など) に近いもの。
SQL 型 ←(マッピング)→ JDBC 型 ←(マッピング)→ Java 言語型
JDBC API 入門 - SQL と Java の型のマッピング
異なるデータベース製品がサポートする SQL の型の間には、相当な相違があります。異なるデータベースが同一の意味を持つ SQL の型をサポートしている場合でも、それらの型に異なる名前を与えていることがあります。たとえば、主要データベースのほとんどが大きなバイナリ値に対する SQL の型をサポートしていますが、Oracle ではこの型を LONG RAW、Sybase では IMAGE、Informix では BYTE、DB2 では LONG VARCHAR FOR BIT DATA とそれぞれ呼んでいます。
JDBC プログラマは、通常は、ターゲットのデータベースが使用している実際の SQL の型名に気を使う必要はありません。多くの場合、JDBC プログラマは、既存のデータベースのテーブルに対してプログラミングをし、そうしたテーブルを作成した正確な SQL の型名に注意を払う必要はありません。
JDBC は、クラス java.sql.Types で総称 SQL の型識別子のセットを定義しています。そのセットの型は、もっとも一般的に使用される SQL の型を表すように設計されています。JDBC API によるプログラミングでは、プログラマは通常、ターゲットのデータベースが使用している正確な SQL の型名を意識することなく、そのセットの JDBC 型を使用して総称 SQL の型を参照することができます。
サンプルコード
ファイル一覧
├── build.gradle
└── src
└── main
└── java
└── JdbcSample.java
build.gradle
plugins {
id 'application'
id 'java'
}
sourceCompatibility = JavaVersion.VERSION_14
repositories {
mavenCentral()
}
dependencies {
// 実行時に H2 Database 1.4.200 を使う
runtimeOnly 'com.h2database:h2:1.4.200'
}
tasks.withType(JavaCompile) {
// Java 14 のプレビュー機能を使う
options.compilerArgs += ['--enable-preview']
}
application {
// Java 14 のプレビュー機能を使う
applicationDefaultJvmArgs = ['--enable-preview']
mainClassName = 'JdbcSample'
}
JdbcSample.java
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Statement;
import java.sql.Types;
import java.util.Arrays;
class JdbcSample {
public static void main(String[] args) throws Exception {
// H2 Database に接続
// mem: インメモリデータベース化
// DB_CLOSE_DELAY=-1: コネクション切断時にDBコンテンツを削除しない
String url = "jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1";
String user = "sa";
String password = "";
Connection con = DriverManager.getConnection(url, user, password);
Statement stmt = con.createStatement();
// テーブルを作成
// いろいろな SQL データ型でカラムを定義
// (Java 14 プレビュー機能で使えるヒアドキュメントっぽく書けるテキストブロック機能を使う)
stmt.execute("""
create table test (
-- 文字列型
my_char CHAR, -- 短い固定長文字列
my_varchar VARCHAR, -- 短い可変長文字列
my_longvarchar LONGVARCHAR, -- 長い可変長文字列
my_clob CLOB, -- Character Large Object
-- バイナリ型
my_binary BINARY(4), -- 小さな固定長バイナリ (SQL データ型の BIT)
my_varbinary VARBINARY(4), -- 小さな可変長バイナリ (SQL データ型の BIT VARYING)
my_longvarbinary LONGVARBINARY(4), -- 大きな可変長バイナリ
my_blob BLOB(4), -- Binary Large Object
-- 真偽値型
my_boolean BOOLEAN, -- 真偽値
-- 整数型
my_smallint SMALLINT, -- short
my_integer INTEGER, -- int
my_bigint BIGINT, -- long
-- 浮動小数点型
my_real REAL, -- 単精度浮動小数点数 float
my_double DOUBLE, -- 倍精度浮動小数点数 double
-- 固定小数点型
my_numeric NUMERIC, -- 固定小数点数
my_decimal DECIMAL, -- 固定小数点型
-- 時間型
my_date DATE, -- 年月日
my_time TIME, -- 時分秒
my_timestamp TIMESTAMP -- 年月日 + 時分秒 + ナノ秒
)""");
// レコードを追加
// (Java 14 プレビュー機能で使えるヒアドキュメントっぽく書けるテキストブロック機能を使う)
stmt.execute("""
insert into test values (
-- 文字列型
'Hello', -- CHAR
'Hello', -- VARCHAR
'Hello', -- LONGVARCHAR
'Hello', -- CLOB
-- バイナリ型
X'CAFEBABE', -- BINARY,
X'CAFEBABE', -- VARBINARY,
X'CAFEBABE', -- LONGVARBINARY,
X'CAFEBABE', -- BLOB,
-- 真偽値型
TRUE, -- BOOLEAN
-- 整数型
32767 , -- SMALLINT
2147483647 , -- INTEGER
9223372036854775807, -- BIGINT
-- 浮動小数点型
123.0001, -- REAL
123.0001, -- DOUBLE
-- 固定小数点型
123.0001, -- NUMERIC
123.0001, -- DECIMAL
-- 時間型
'2001-02-03', -- DATE
'04:05:06', -- TIME
'2001-02-03 04:05:06.123456789' -- TIMESTAMP
)""");
// レコードを取得
ResultSet rs = stmt.executeQuery("select * from test");
while (rs.next()) {
// カラムの JDBC 型に対する Java オブジェクトの型を取得
System.out.println("カラム名 - JDBC 型 - データベース固有の SQL 型 - Java オブジェクトの型");
ResultSetMetaData rsmd = rs.getMetaData();
for (int i = 1; i <= rsmd.getColumnCount(); i++) {
System.out.println(
rsmd.getColumnName(i) + " - " +
getJdbcTypeName(rsmd.getColumnType(i)) + " - " +
rsmd.getColumnTypeName(i) + " - " +
rsmd.getColumnClassName(i));
}
System.out.println();
// カラムの値を取得していく
System.out.println("カラム名 - カラムの値");
// 文字列型
System.out.println("my_char=" + rs.getString("my_char"));
System.out.println("my_varchar=" + rs.getString("my_varchar"));
System.out.println("my_longvarchar=" + rs.getString("my_longvarchar"));
System.out.println("my_clob=" + rs.getClob("my_clob"));
// バイナリ型
System.out.println("my_binary=" + Arrays.toString(rs.getBytes("my_binary")));
System.out.println("my_varbinary=" + Arrays.toString(rs.getBytes("my_varbinary")));
System.out.println("my_longvarbinary=" + Arrays.toString(rs.getBytes("my_longvarbinary")));
System.out.println("my_blob=" + rs.getBlob("my_blob"));
// 真偽値型
System.out.println("my_boolean=" + rs.getBoolean("my_boolean"));
// 整数型
System.out.println("my_smallint=" + rs.getShort("my_smallint"));
System.out.println("my_integer=" + rs.getInt("my_integer"));
System.out.println("my_bigint=" + rs.getBigDecimal("my_bigint"));
// 浮動小数点型
System.out.println("my_real=" + rs.getFloat("my_real"));
System.out.println("my_double=" + rs.getDouble("my_double"));
// 固定小数点型
System.out.println("my_numeric=" + rs.getBigDecimal("my_numeric"));
System.out.println("my_decimal=" + rs.getBigDecimal("my_decimal"));
// 時間型
System.out.println("my_date=" + rs.getDate("my_date"));
System.out.println("my_time=" + rs.getTime("my_time"));
System.out.println("my_timestamp=" + rs.getTimestamp("my_timestamp"));
}
stmt.close();
con.close();
}
// JDBC 型の名称を取得する
private static String getJdbcTypeName(int type) throws IllegalAccessException {
Field[] fs = Types.class.getDeclaredFields();
for (Field f : fs) {
if (type == f.getInt(null)) {
return f.getName();
}
}
return null;
}
}
実行結果
Gradle の run タスクで実行。
$ gradle run
Starting a Gradle Daemon (subsequent builds will be faster)
> Task :compileJava
注意:/Users/foo/bar/src/main/java/JdbcSample.javaはプレビュー言語機能を使用します。
注意:詳細は、-Xlint:previewオプションを指定して再コンパイルしてください。
> Task :run
カラム名 - JDBC 型 - データベース固有の SQL 型 - Java オブジェクトの型
MY_CHAR - CHAR - CHAR - java.lang.String
MY_VARCHAR - VARCHAR - VARCHAR - java.lang.String
MY_LONGVARCHAR - VARCHAR - VARCHAR - java.lang.String
MY_CLOB - CLOB - CLOB - java.sql.Clob
MY_BINARY - VARBINARY - VARBINARY - [B
MY_VARBINARY - VARBINARY - VARBINARY - [B
MY_LONGVARBINARY - VARBINARY - VARBINARY - [B
MY_BLOB - BLOB - BLOB - java.sql.Blob
MY_BOOLEAN - BOOLEAN - BOOLEAN - java.lang.Boolean
MY_SMALLINT - SMALLINT - SMALLINT - java.lang.Short
MY_INTEGER - INTEGER - INTEGER - java.lang.Integer
MY_BIGINT - BIGINT - BIGINT - java.lang.Long
MY_REAL - REAL - REAL - java.lang.Float
MY_DOUBLE - DOUBLE - DOUBLE - java.lang.Double
MY_NUMERIC - DECIMAL - DECIMAL - java.math.BigDecimal
MY_DECIMAL - DECIMAL - DECIMAL - java.math.BigDecimal
MY_DATE - DATE - DATE - java.sql.Date
MY_TIME - TIME - TIME - java.sql.Time
MY_TIMESTAMP - TIMESTAMP - TIMESTAMP - java.sql.Timestamp
カラム名 - カラムの値
my_char=Hello
my_varchar=Hello
my_longvarchar=Hello
my_clob=clob0: 'Hello'
my_binary=[-54, -2, -70, -66]
my_varbinary=[-54, -2, -70, -66]
my_longvarbinary=[-54, -2, -70, -66]
my_blob=blob0: X'cafebabe'
my_boolean=true
my_smallint=32767
my_integer=2147483647
my_bigint=9223372036854775807
my_real=123.0001
my_double=123.0001
my_numeric=123.0001
my_decimal=123.0001
my_date=2001-02-03
my_time=04:05:06
my_timestamp=2001-02-03 04:05:06.123457
BUILD SUCCESSFUL in 6s
2 actionable tasks: 2 executed