JavaでPostgreSQLを動かしてみる。
環境
- macOS Mojave
- Eclipse 4.7.3
- PostgreSQL 11.4
- JDBC Driver 42.2.5(postgresql-42.2.5.jar)
JDBC Driverの導入
PostgreSQLのRDBにアクセスするためのJavaの標準APIとしてJDBCドライバが必要となる。
まずはそのダウンロードから。
https://jdbc.postgresql.org/download.html#current
ここでは postgresql-42.2.5.jar を使用する。
それを今回のプロジェクト下の任意の場所に配置する(lib/
の中が分かりやすい?)
しかしこのままではどこを参照しているのかが分からないのでパスを設定する必要がある。
macであれば
postgresql-42.2.5.jar
をクリックしてプロジェクトタブ --> プロパティ --> Javaのビルドパス --> ライブラリ --> 外部JARの追加 -->postgresql-42.2.5.jar
を探してopen --> 適用して閉じる
で参照ライブラリの中にpostgresql-42.2.5.jar
が参照されていたらOK
使用するDB
今回は全て以前使用したものを再利用していく。
ユーザーは以下の通り
customer=# \l
List of databases
Name | Owner | Encoding | Collate | Ctype | Access privileges
-----------+-------------+----------+---------+-------+-----------------------
customer | sf213471118 | UTF8 | C | C |
テーブルはcustomerテーブルを使用する
customer=# \d
List of relations
Schema | Name | Type | Owner
--------+----------+-------+-------------
public | customer | table | sf213471118
customerテーブルの中身は以下の通り
customer=# SELECT * FROM customer;
id | name | gender | age
-----------------+----------+--------+-----
10001 | 田中太郎 | m | 31
10002 | 中村花子 | w | 44
10003 | 佐藤一郎 | m | 20
10004 | 内田彩 | w | 18
10005 | 高橋次郎 | m | 56
10006 | 中里悟 | m | 34
(6 rows)
Javaの記述における大事な部分
記述していく上で忘れないようにしたいところを残しておく。
例外処理
public static void main(String[] args) throws Exception {
try {
System.out.println("DB access start");
PostgreSQL_test.dbConnect();
} catch (Exception e) {
System.out.println("error main()");
e.printStackTrace();
} finally {
System.out.println("DB access finished");
}
}
例外処理はtry-catch(-finally)
で記述する。
この例だとException e
としているためエラーの場所しか特定できないが、catchの条件を変えて並列記述することでエラー内容を瞬時に把握することも可能。
例えば
try {
file_reader = new FileReader(customer);
~
} catch (FileNotFoundException f) { // ファイル探索エラー
System.out.println("cannot find file");
f.printStackTrace();
} catch (IOException i) { //ファイル入出力エラー
System.out.println("in/out error");
i.printStackTrace();
} finally {
try {
if(file_reader != null) {
file_reader.close();
}
} catch (IOException i) { //ファイルclose中エラー
System.out.println(i);
i.printStackTrace();
}
}
というフローがあったとして、
①try - catch - catch
のほう
-
new FileReader(customer)
をしたがそのファイル名が見つからないとき - customerファイルはあるが出力できなかったとき
の2つを考慮して分岐してある。
②finally - try - catch
のほう
- close中のエラー
のみ検出している。
例外処理はFileNotFoundException
やIOException
以外にも沢山あるが、Exception
とすれば全てのエラーを引っ掛けることができる(2つ上のプログラムの通り場所の特定くらいしか思いつかないが。。。)
DB接続に向けて
JDBCの初期化
DBに接続する前にJDBCドライバを初期化する必要がある。
PostgreSQLの場合は以下のように記述する
Class.forName("org.postgresql.Driver").newInstance();
DB接続の確立/DB切断
またDBの接続を確立させるためにDriverManagerクラスが標準で持っているgetConnectionメソッドを使用する必要がある。
connection = DriverManager.getConnection( <URL> , <USER>, <PASSWORD>);
URLに関してはjdbc:postgresql://<場所>:<ポート番号>/<DB名>
で表記する。
今回は以下で設定した。
場所 | ポート番号 | DB名 |
---|---|---|
localhost | 5432 | customer |
切断に関しては、万が一のことも考えてfinallyで行うようにする。
rs.close(); //rsはResultSetインターフェースの変数
SQL文の記述
SQLをDBに送るときには、まずConnectionインターフェースで定義されているcreateStatementメソッドを使用してステートメントを作成する必要がある(SQLを送るときに必ずセットで記述するもの)
statement = con.createStatement();
上記が終わったらSQL文を問い合わせる記述をする
resultset = stm.executeQuery(" <SQL文> ");
データの出力
ResultSetインターフェースの**next()**メソッドで1行づつ処理を行うことができる。
while (rs.next()) {
System.out.println(rs.getInt("<column>"));
System.out.println(rs.getString("<column>"));
}
今回のJava記述
package customer;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class PostgreSQL_test {
public static void main(String[] args) throws Exception {
try {
System.out.println("DB access start");
PostgreSQL_test.dbConnect();
} catch (Exception e) {
System.out.println("error main()");
e.printStackTrace();
} finally {
System.out.println("DB access finished");
}
}
private static void dbConnect() throws Exception {
Connection con = null;
Statement stm = null;
ResultSet rs = null;
int num = 1;
String url = "jdbc:postgresql://localhost:5432/customer";
String user = "sf213471118";
String password = ""; //今回パスワードは設定していない
try {
Class.forName("org.postgresql.Driver").newInstance();
con = DriverManager.getConnection(url, user, password);
stm = con.createStatement();
rs = stm.executeQuery("SELECT * FROM customer");
while (rs.next()) {
System.out.println("[" + num + " 件目]");
num++;
System.out.println("id : " + rs.getString("id"));
System.out.println("name : " + rs.getString("name"));
System.out.println("gender : " + rs.getString("gender"));
System.out.println("age : " + rs.getInt("age"));
}
} catch(SQLException e) {
System.out.println("error dbConnect()");
e.printStackTrace();
}finally {
try {
if ((rs != null)||(stm != null)||(con != null)) {
rs.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
これを動かすと、以下が返ってくる。
DB access start
[1 件目]
id : 10001
name : 田中太郎
gender : m
age : 31
[2 件目]
id : 10002
name : 中村花子
gender : w
age : 44
[3 件目]
id : 10003
name : 佐藤一郎
gender : m
age : 20
[4 件目]
id : 10004
name : 内田彩
gender : w
age : 18
[5 件目]
id : 10005
name : 高橋次郎
gender : m
age : 56
[6 件目]
id : 10006
name : 中里悟
gender : m
age : 34
DB access finished
本当であればrs.next()
で現在の件数名を出力したかったのだが、よく分からなかったので姑息な手で出力してしまった。。。
どなたかやり方を教えていただけるととても嬉しいです
【追記】 2019/7/29
コメントを下さりありがとうございます。以下の通り修正しました。
①ループの部分の試行回数をrs.getRow()
で受取り
while (rs.next()) {
System.out.println("[" + rs.getRow() + " 件目]"); /* 修正部分 */
System.out.println("id : " + rs.getString("id"));
System.out.println("name : " + rs.getString("name"));
System.out.println("gender : " + rs.getString("gender"));
System.out.println("age : " + rs.getInt("age"));
}
②close漏れを修正しました
try {
if ((rs != null)||(stm != null)||(con != null)) {
rs.close();
stm.close(); /* 修正部分 */
con.close(); /* 修正部分 */
}
} catch (Exception e) {
e.printStackTrace();
}
改めてありがとうございました。