#1時間でOracle接続できるかな(備忘録)#
Oracleの公式にあったクイックスタートという記事を参考にOracleデータベースをインストールしたので、今回は実際に接続を行っていきたいと思います。
これがその記事ですね。
Oracle Database XEクイックスタート
環境
OSはWindows
Oracleは21c
んで、Eclipseを使用する
##Eclipseにソースコードを張り付ける##
まずは、「Oracle Database XEへの接続」という項目の中からJAVAを探して、そのソースコードを全て張り付けちゃいましょう。
SQLExceptionという例外が発生する可能性があるので、try~catch文で囲んでくださいね。
あっ、ソースコードの流れはこんな感じです。
結論として、この処理では「Hello World!」という文をコンソールに表示します。
- オラクルデータベースのデータソースを作成する。
- オラクルデータベースのURLを設定する
- ユーザ名とパスワードを設定する
- データベースに接続する
- SQL文を組み立てる
- 結果を取得する
- 結果を表示する
ちなみに、HelloWorld!を取得しているdualというテーブルはOracle用のダミーテーブルです。
実際にdualというテーブルは作成しなくてもよいですよ。
##例外が発生しました1##
java.sql.SQLRecoverableException: IOエラー: The Network Adapter could not establish the connection
これは「ネットワーク アダプタが接続を確立できませんでした」という意味です。
ネットワークアダプタとは、コンピュータなどの機器を通信ネットワークに接続するための装置のことで、OracleでいうとOracleリスナーのことですね。
##例外1を解決方法##
ということで、解決していきましょう。
まずは、Oracleデータベース自体が動いているかを確認します。
なぜ確認するのかというと、Oracleデータベースが動いていないと、当然その中のリスナーも動かないと思ったからです。
さて、Oracleデータベースが動いているかはインスタンスが起動しているかで確認できます。
###インスタンスの起動の確認###
インスタンスとはデータを操作するための装置です。
インスタンスが起動していないとOracleデータベースも動きません。
逆にインスタンスが起動していれば、Oracleデータベースも動いているということです。
以下のSQL文を打つことで確認します
SELECT INSTANCE_NAME,STATUS FROM V$INSTANCE;
インスタンスを確認するには、V$INSTANCE
というビューを使用します。
INSTANCE_NAME
がインスタンスの名前で、STATUS
がインスタンスの状態を表しています。
早速確認していきましょう。
SQL> SELECT INSTANCE_NAME,STATUS FROM V$INSTANCE;
INSTANCE_NAME STATUS
-------------------------------- ------------------------
xe OPEN
これを見るとxe
というインスタンスが、OPEN
実行可能状態になっていますね。
インスタンスが既に起動していることを確認できました。
###リスナーの起動の確認###
次にリスナーが動いていることを確認しましょう。
リスナーとはクライアントとデータベースサーバをつなぐものです。
クライアントの接続要求を待っており、要求が来たら目的のデータベースに接続してくれます。
逆にリスナーがいなくては、いくらサーバが「準備OK。早く要求来ないかな」と思っていても待ちぼうけをくらうだけです。
リスナーのステータスを確認するためには、SQLPLUSから出た後にlsnrctl status
で確認できます。
C:\Users\user>lsnrctl status
LSNRCTL for 64-bit Windows: Version 21.0.0.0.0 - Production on 27-12月-2021 09:30:01
Copyright (c) 1991, 2021, Oracle. All rights reserved.
(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.0.15)(PORT=1521)))に接続中
TNS-12541: TNS: リスナーがありません。
TNS-12560: TNS: プロトコル・アダプタ・エラー
TNS-00511: リスナーがありません。
64-bit Windows Error: 61: Unknown error
(DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC1521)))に接続中
TNS-12541: TNS: リスナーがありません。
TNS-12560: TNS: プロトコル・アダプタ・エラー
TNS-00511: リスナーがありません。
64-bit Windows Error: 2: No such file or directory
####TNS-00511: リスナーがありません
と表示されました。####
本当にリスナーがないのか確認しましょう。
リスナーの設定ファイル、listener.oraを開いてっと。
LISTENER =
って見えますよね。これがリスナーの設定です。
設定もされているし、どうやらリスナーが動いていないだけのようですね。
では、起動しましょう。
####リスナーの起動####
lsnrctl start
でリスナーを起動できます。
ただし、この処理はインストールしたときと同じユーザでないとできません。
管理者権限があるユーザでインストールしたはずなので、そのユーザでログインして、
コマンドプロンプトを管理者として実行してと
C:\Windows\system32>lsnrctl start
LSNRCTL for 64-bit Windows: Version 21.0.0.0.0 - Production on 27-12月-2021 09:40:14
Copyright (c) 1991, 2021, Oracle. All rights reserved.
tnslsnrを起動しています。お待ちください...
TNSLSNR for 64-bit Windows: Version 21.0.0.0.0 - Production
システム・パラメータ・ファイルはC:\app\user\product\21c\homes\OraDB21Home1\network\admin\listener.oraです。
ログ・メッセージをC:\app\user\product\21c\diag\tnslsnr\DESKTOP-9F93K3D\listener\alert\log.xmlに書き込みました。
リスニングしています: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.0.15)(PORT=1521)))
リスニングしています: (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(PIPENAME=\\.\pipe\EXTPROC1521ipc)))
(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.0.15)(PORT=1521)))に接続中
リスナーのステータス
------------------------
別名 LISTENER
バージョン TNSLSNR for 64-bit Windows: Version 21.0.0.0.0 - Production
開始日 27-12月-2021 09:40:21
稼働時間 0 日 0 時間 0 分 12 秒
トレース・レベル off
セキュリティ ON: Local OS Authentication
SNMP OFF
デフォルト・サービス XE
パラメータ・ファイル C:\app\user\product\21c\homes\OraDB21Home1\network\admin\listener.ora
ログ・ファイル C:\app\user\product\21c\diag\tnslsnr\DESKTOP-9F93K3D\listener\alert\log.xml
リスニング・エンドポイントのサマリー...
(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.0.15)(PORT=1521)))
(DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(PIPENAME=\\.\pipe\EXTPROC1521ipc)))
サービスのサマリー...
サービス"CLRExtProc"には、1件のインスタンスがあります。
インスタンス"CLRExtProc"、状態UNKNOWNには、このサービスに対する1件のハンドラがあります...
コマンドは正常に終了しました。
無事に起動できました。
もう一度リスナーの確認をしましょう。
C:\Windows\system32>lsnrctl status
LSNRCTL for 64-bit Windows: Version 21.0.0.0.0 - Production on 27-12月-2021 09:41:05
Copyright (c) 1991, 2021, Oracle. All rights reserved.
(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.0.15)(PORT=1521)))に接続中
リスナーのステータス
------------------------
別名 LISTENER
バージョン TNSLSNR for 64-bit Windows: Version 21.0.0.0.0 - Production
開始日 27-12月-2021 09:40:21
稼働時間 0 日 0 時間 0 分 48 秒
トレース・レベル off
セキュリティ ON: Local OS Authentication
SNMP OFF
デフォルト・サービス XE
パラメータ・ファイル C:\app\user\product\21c\homes\OraDB21Home1\network\admin\listener.ora
ログ・ファイル C:\app\user\product\21c\diag\tnslsnr\DESKTOP-9F93K3D\listener\alert\log.xml
リスニング・エンドポイントのサマリー...
(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=192.168.0.15)(PORT=1521)))
(DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(PIPENAME=\\.\pipe\EXTPROC1521ipc)))
(DESCRIPTION=(ADDRESS=(PROTOCOL=tcps)(HOST=127.0.0.1)(PORT=5500))(Security=(my_wallet_directory=C:\APP\USER\PRODUCT\21C\admin\XE\xdb_wallet))(Presentation=HTTP)(Session=RAW))
サービスのサマリー...
サービス"424cd63be20a4b1e9a48814308378211"には、1件のインスタンスがあります。
インスタンス"xe"、状態READYには、このサービスに対する2件のハンドラがあります...
サービス"CLRExtProc"には、1件のインスタンスがあります。
インスタンス"CLRExtProc"、状態UNKNOWNには、このサービスに対する1件のハンドラがあります...
サービス"XE"には、1件のインスタンスがあります。
インスタンス"xe"、状態READYには、このサービスに対する2件のハンドラがあります...
サービス"XEXDB"には、1件のインスタンスがあります。
インスタンス"xe"、状態READYには、このサービスに対する1件のハンドラがあります...
サービス"xepdb1"には、1件のインスタンスがあります。
インスタンス"xe"、状態READYには、このサービスに対する2件のハンドラがあります...
コマンドは正常に終了しました。
リスナーの起動を確認できましたね。
ちなみに、リスナーを終了させるには lsnrctl stopでできますよ。
C:\Windows\system32>lsnrctl stop
LSNRCTL for 64-bit Windows: Version 21.0.0.0.0 - Production on 27-12月-2021 09:41:34
Copyright (c) 1991, 2021, Oracle. All rights reserved.
(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.0.15)(PORT=1521)))に接続中
コマンドは正常に終了しました。
##例外が発生しました2##
java.sql.SQLRecoverableException: IOエラー: The Network Adapter could not establish the connection (CONNECTION_ID=MK2DMn9nST+K2WaH6ac9PA==)
リスナーが起動したのに実行できませんでした。
そんな方も慌てる必要はありません。
まずは接続するURLが間違っていないか確認してください。
というか、まず最初に疑わないといけないのはこれなんですけどね(-_-;)
URLの確認を行う
URLの設定のルールは以下の通りです。
jdbc:oracle:thin@//[ホスト名]:[ポート番号]/[DBサービス名]
実際に書いたURLはこれです。
jdbc:oracle:thin:@//localhost:1521/XEPDB1
書き方は一致しているようですね。
ちなみに、/[DBサービス名]
の部分が:[DBサービス名]
になっているサンプルソースを見たことありますが、
動きませんからね。(私はここでつまずいた。どれだけ悩んだことか!!!)
####ホスト名、ポート番号、サービス名を確認する####
まずは、ホスト名とポート番号を確認しましょう。
ORACLE_HOMEディレクトリではないhomesディレクトリの中にnetwork/adminディレクトリがあると思います。
この中にはリスナー設定ファイルのlistener.oraと一緒に
クライアントが呼べるサービスの設定が書かれているtnsnames.oraがあると思います。
この中にあるXEPDB1
の値の確認をします。
HOSTで設定されている値がホスト名で、PORTはポート番号です。
また、SERVICE_NAMEがサービス名です。
なので、写真の例だとこんな感じですね。
ホスト名:192.168.0.15
ポート番号:1521
サービス名:XEPDB1
おや、localhostではないIPアドレスが設定されていますね。
おそらくこれが原因でしょう。
jdbc:oracle:thin:@//localhost:1521/XEPDB1
を
jdbc:oracle:thin:@//192.168.0.15:1521/XEPDB1
に直してと。
##例外が発生しました3##
リスナーの起動も確認し、クライアントで実行するURL(接続記述子)も妥当なものにしました。
今度こそ!!!
java.sql.SQLException: ORA-01017: ユーザー名/パスワードが無効です。ログオンは拒否されました。
……もう堪忍してぇ。
ユーザー名/パスワードが一致していなかったため、ログオンは拒否されたみたいです。
SYSTEMはOracleのシステムユーザだから、パスワードが間違っているのかな。
インストール時に管理用アカウントのパスワードを設定したときのパスワードとは違うものだからだな。
まぁ、要するにパスワード間違えんなってこと。
実際にGetStartedWithXE、ではなくインストール時に設定したパスワードで実行するとログオンできました。
ちなみに、setUserに"sys as sysdba"setPasswordにインストール時に入力したパスワードを入力したら起動できました。
これはOracleのadmin権限を持つユーザがsys as sysdbaだからです。
ようやくつながりました。
完成したソースがこちらです。
package databaseSample;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import oracle.jdbc.datasource.impl.OracleDataSource;
public class app {
public static void main(String args[]) {
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
OracleDataSource ods = new OracleDataSource();
ods.setURL("jdbc:oracle:thin:@//192.168.0.15:1521/XEPDB1");
ods.setUser("system");
ods.setPassword("pass");
conn = ods.getConnection();
stmt = conn.prepareStatement("SELECT 'Hello World!'FROM dual");
rs = stmt.executeQuery();
while (rs.next()) {
System.out.println(rs.getString(1));
}
}catch(SQLException ex) {
ex.printStackTrace();
}finally{
try {
conn.close();
} catch (SQLException e) {
// TODO 自動生成された catch ブロック
e.printStackTrace();
}
try {
stmt.close();
} catch (SQLException e) {
// TODO 自動生成された catch ブロック
e.printStackTrace();
}
try {
rs.close();
} catch (SQLException e) {
// TODO 自動生成された catch ブロック
e.printStackTrace();
}
}
}
}
んで、これもできます
package databaseSample;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class app {
public static void main(String args[]) {
try {
String url = "jdbc:oracle:thin:@//192.168.0.15:1521/XEPDB1";
String user = "system";
String password = "pass";
Class.forName("oracle.jdbc.OracleDriver");
Connection conn = DriverManager.getConnection(url, user, password);
PreparedStatement stmt = conn.prepareStatement("SELECT 'Hello World!'FROM dual");
ResultSet rslt = stmt.executeQuery();
while (rslt.next()) {
System.out.println(rslt.getString(1));
}
}catch(SQLException ex) {
ex.printStackTrace();
}catch(ClassNotFoundException ex) {
ex.printStackTrace();
}
}
}
実行結果
Hello World!
はい、というわけで1時間(執筆の時間入れたら1時間超えたけど)でJDBC接続できました。
ユーザ作成はまたの次回に書きたいと思います。
それでは、ばい