Java

JDBCエラーに苦しまされたよ【Exception in thread “main” java.sql.SQLException: No suitable driver found for jdbc:postgresql://localhost:/postgres】

java_アイキャッチ

こんにちは!ゆーたろうです。

私はこれまでは既存のソースを改良することが多かったので、先輩たちが書いたソースの恩恵を最大限に享受していました。

しかし先日、1からDBへのアクセス処理を書くことになり、たくさんハマり大変苦しんだので、忘れないようにここに残していこうと思います。

やろうとしたこと

EclipseでJavaを使い、PostgreSQLにあるデータベースに接続すること

こうやって文字で書いたら、めーっちゃ簡単そうですよね。

私も最初取り組む前は簡単に実装できると思っていました。。。まさか沼に入ることになるとはつゆ知らず。。

まず、Javaを使ってデータベースにアクセスする方法を調べる

私は普段PHPを使ってデータベースにアクセスすることがほとんどなので、そもそもJavaを使ったアクセス方法が分かりませんでした。

なのでネットで調べてみるといい教材がありましたので、こちらを参考に組むことに。

とにかくすぐJavaからPostgreSQLに接続を試したい

いざ実行!しかしエラーに…

なりました。。。問題が発生したソースがこちらです。

 //-----------------
 // DB接続
//-----------------
connection = DriverManager.getConnection("jdbc:postgresql://"+ mHost + ":" + mPort + "/" + mDBname, mUser, mPass);
statement = connection.createStatement();

ホスト名やパスワードなどは、xmlから読みこむようにしています。

xmlの定義は、前の記事で書いたフォーマットです。

エラー内容

Exception in thread “main” java.sql.SQLException: No suitable driver found for jdbc:postgresql://localhost:5432/postgres
at java.sql.DriverManager.getConnection(DriverManager.java:689)
at java.sql.DriverManager.getConnection(DriverManager.java:247)
at AppMain.main(AppMain.java:132)

DriverManager.getConnection()の部分で止まっていました。

そもそもDBにアクセスすらできてないようですね。

そしてここから、試行錯誤の連続でした。

したこと

など、思いつくものを手当たり次第にやってみました。

そして翌日、ついに解決へ!

原因:JDBCのjarファイルをEclipseに設定していなかったため

でした。

JavaでDB接続が出来ません。のサイトに出会い、そこに書かれた「postgresql-9.4-1201.jdbc4のJarファイルを、ビルド・パスに設定」で検索してみました。

次に「Java:JDBCドライバを使ってPostgreSQLにアクセスする手順」のサイトを見つけ、記事に沿って進めてみました。

PostgreSQL JDBC Downloadのページから、2020年9月4日時点で最新の「PostgreSQL JDBC 4.2 Driver, 42.2.16」をダウンロードします。

その後、読みこませたいワークスペースの下にlibを作ってその中に↑のjarファイルを置きました。

フォルダ構成
root
└workspace
 └プロジェクト名
  ├.settings
  ├bin
  ├src
  ├.classpath
  ├.project
  └lib・・・新規作成し、ここにjarファイルを置く
   └postgresql-42.2.16.jar

そして、Java Build Pathを設定しました。

するとどうでしょう!エラーなくデータベースに接続できました!!

完成後のソース

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.postgresql.jdbc3.Jdbc3PoolingDataSource;




public class AppMain {
	/**
	 * 定数定義
	 */
	final static String CONFIG_XML_FILE_PATH = "./property.xml";
	final static String NODE_NODENAME_HOST = "host";
	final static String NODE_NODENAME_PORT = "port";
	final static String NODE_NODENAME_DBNAME = "dbname";
	final static String NODE_NODENAME_USER = "user";
	final static String NODE_NODENAME_PASS = "pass";
	final static String NODE_NODENAME_ENCODE = "encoding";
	final static String NODE_NODENAME_TIMEOUT = "timeout";
	final static String NODE_NODENAME_TERMMONTH = "term_months";
	final static String NODE_NODENAME_LOGLEVEL = "log_level";
	final static String NODE_NODENAME_SCHEMA = "schema";
	// private PGConnectionPoolDataSource ds = null;
	
	@SuppressWarnings("deprecation")
	private Jdbc3PoolingDataSource ds = null;

	
	public static void main(String[] args) throws Exception	{
		/**
		 * 変数定義
		 */
		boolean execFlag = true;			//実行継続フラグ t=実行、f=中断し終了する
        Connection connection = null;
        Statement statement = null;
        ResultSet resultSet = null;
		
		//データベース関連(設定ファイルよりセット)
		int mTimeout = 0;
		int mPort    = 0;
		String mHost = "";
		String mUser = "";
		String mPass = "";
		String mDBname = "";
		String mSchema = "";
		String mEncode = "";
		//アプリケーション関連(設定ファイルよりセット)
		int mTermMonths = 3;
		String mLogLevel = "";
		
		/**
		 * 設定ファイルの読み込み
		 */
		try {
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			DocumentBuilder builder = factory.newDocumentBuilder();
			Document document = builder.parse(CONFIG_XML_FILE_PATH);
			// XMLノードを取得する
			Element root = document.getDocumentElement();
			// ノードの一覧を取得
			NodeList nodeList = root.getChildNodes();
			
			
			for(int i = 0; i < nodeList.getLength(); i++){
				Node configNode = nodeList.item(i);
				
				if(configNode.getNodeType() == Node.ELEMENT_NODE){
					Element configElement = (Element)configNode;
					System.out.println("[" + configElement.getNodeName() + "]");
					NodeList configElementChildrenNodeList = configElement.getChildNodes();
					
					for(int j = 0; j < configElementChildrenNodeList.getLength(); j++){
						Node node = configElementChildrenNodeList.item(j);
						
						if(node.getNodeType() == Node.ELEMENT_NODE){
							System.out.println(String.format("%s.%s=%s",configElement.getNodeName(), node.getNodeName(), node.getTextContent()));

							if(node.getNodeName() == NODE_NODENAME_TERMMONTH && !node.getTextContent().equals("")) {
								//指定期間のセット
								mTermMonths = Integer.valueOf(node.getTextContent());
							}else if (node.getNodeName() == NODE_NODENAME_HOST) {
								//ホスト名のセット
								mHost = node.getTextContent();
							}else if (node.getNodeName() == NODE_NODENAME_PORT) {
								//ポート番号のセット
								mPort = Integer.valueOf(node.getTextContent());
							}else if (node.getNodeName() == NODE_NODENAME_DBNAME) {
								//データベース名のセット
								mDBname = node.getTextContent();
							}else if (node.getNodeName() == NODE_NODENAME_USER) {
								//ユーザ名のセット
								mUser = node.getTextContent();
							}else if (node.getNodeName() == NODE_NODENAME_PASS) {
								//パスワードのセット
								mPass = node.getTextContent();
							}else if (node.getNodeName() == NODE_NODENAME_ENCODE) {
								//エンコードのセット
								mEncode = node.getTextContent();
							}else if (node.getNodeName() == NODE_NODENAME_TIMEOUT) {
								//タイムアウトのセット
								mTimeout = Integer.valueOf(node.getTextContent());
							}else if (node.getNodeName() == NODE_NODENAME_LOGLEVEL) {
								//ログレベルのセット
								mLogLevel = node.getTextContent();
							}else if (node.getNodeName() == NODE_NODENAME_SCHEMA) {
								//ログレベルのセット
								mSchema = node.getTextContent();
							}
						}
					}
				}
			}
		}catch(Exception e) {
			System.out.println("エラー: " + e);
			execFlag = false;
		}
		
		
		//正常に設定ファイルが読みこめた場合のみ処理する
		if(execFlag) {
			try {
	            //-----------------
	            // DB接続
	            //-----------------

				Class.forName("org.postgresql.Driver");
	            connection = DriverManager.getConnection("jdbc:postgresql://"+ mHost + ":" + mPort + "/" + mDBname, mUser, mPass);
				statement = connection.createStatement();

	            
	            //-----------------
	            // SQLの発行
	            //-----------------
	            //ユーザー情報のテーブル
	            resultSet = statement.executeQuery("SELECT * FROM pg_shadow");

	            //-----------------
	            // 値の取得
	            //-----------------
	            // フィールド一覧を取得
	            List<String> fields = new ArrayList<String>();
	            ResultSetMetaData rsmd = resultSet.getMetaData();
	            for (int i = 1; i <= rsmd.getColumnCount(); i++) {
	                fields.add(rsmd.getColumnName(i));
	            }

	            //結果の出力
	            int rowCount = 0;
	            while (resultSet.next()) {
	                rowCount++;

	                System.out.println("---------------------------------------------------");
	                System.out.println("--- Rows:" + rowCount);
	                System.out.println("---------------------------------------------------");

	                //値は、「resultSet.getString(<フィールド名>)」で取得する。
	                for (String field : fields) {
	                    System.out.println(field + ":" + resultSet.getString(field));
	                }
	            }


	        } finally {
	            //接続を切断する
	            if (resultSet != null) {
	                resultSet.close();
	            }
	            if (statement != null) {
	                statement.close();
	            }
	            if (connection != null) {
	                connection.close();
	            }
	        }
		}
		
	}
}


実行結果

[Database]
Database.host=localhost
Database.port=5432
Database.dbname=postgres
Database.user=postgres
Database.pass=postgres
Database.encoding=SJIS
Database.timeout=9000
[Application]
Application.log_level=info
---------------------------------------------------
--- Rows:1
---------------------------------------------------
usename:MgrUser
usesysid:16384
usecreatedb:f
usesuper:t
userepl:f
usebypassrls:f
valuntil:null
useconfig:null

無事にうまくいきました!

本当に良かったです。ホッとしました。