- ベストアンサー
JDBCで複数のクラスファイルを作成しアクセスしようとしたときに起こる問題点
Javaとデータベース(oracle)を連動させて、Statementなどを実行して値をとってこようとしています。1つのJavaファイル内にてコンパイル、実行はできたのですが、複数のJavaファイルに切り出したときにコンパイルはできるのですが、実行すると Exception in thread "main" java.lang.NullPointerException at DBAccess.Zenkenkensaku.zenkenkensaku(Zenkenkensaku.java:21) at DBAccess.JavaDataAccess.main(JavaDataAccess.java:19) と出てしまってできません。エラーメッセージを見る限り、ステートメントの作成がうまくできていない感じがするのですが、何がいけなかったのでしょうか、原因がわかりません。よろしくお願いします。下にそのファイルを書きます。 JavaDataAccess.java //DBにアクセスするクラスの切り出し package DBAccess; //JDBC APIをインポート import java.sql.*; //メイン class JavaDataAccess { public static void main (String args[]) throws SQLException, ClassNotFoundException { //接続の呼び出し ConnectClose connectclose1 = new ConnectClose(); connectclose1.Connect(); //全件検索の呼び出し Zenkenkensaku zenkenkensaku1 = new Zenkenkensaku(); zenkenkensaku1.zenkenkensaku(); //接続をクローズする呼び出し ConnectClose connectclose2 = new ConnectClose(); connectclose2.Close(); } } Zenkenkensaku.java //全件検索ファイル //パッケージ package DBAccess; //JDBC APIをインポート import java.sql.*; class Zenkenkensaku { //宣言と初期化 Connection conn = null; Statement stmt = null; ResultSet rset = null; //全件検索の内容 public void zenkenkensaku() throws SQLException { // ステートメントを作成 stmt = conn.createStatement(); //問合せの実行 rset = stmt.executeQuery("select 商品コード, 商品名, 単価 from 商品"); // 問合せ結果の表示 while( rset.next()){ //列番号による指定 System.out.println (rset.getInt(1) + "\t" + rset.getString(2) + "\t" + rset.getInt(3)); } } }
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
- ベストアンサー
>connについてなのですが、connは接続とクローズのファイルで定義しています。ただ、使いまわせていないという状況でしょうか? 見たところ、ただ単にConnectCloseの中にConnectionを準備しているだけのように見えるのですが。このConnectClose内のConnectionは、いつどこでZenkenkensakuクラス内のConnectionフィールドに設定されているのでしょう? されていないですよね? ということは、 「ConnectCloseでConnectionを作成する」 「ZenkenkensakuのnullのままのConnectionからStatementを作る」 「ConnectCloseのまったく使われないConnectionをとじる」 という感じになってませんか? どこかで、zenkenkensaku1.conn = connectclose1.conn; というような感じでConnectCloseのConnectionをZenkenkensakuのConnectionに設定してやらないとnullのままではありませんか?
その他の回答 (3)
- PED02744
- ベストアンサー率40% (157/390)
ANo.3です。 「使いまわす」の意味がやっとわかりました。そして、何を勘違いされているのかも。 クラスを分割した場合、それぞれのクラスは別々なので、他のクラスで宣言された内容はわからないのです。 だから、Aというクラスでaという変数が宣言されたとしても、Bというクラスではaという変数の値は見えないのです。 さらに、Aというクラスで宣言されたaとBというクラスで宣言されたaは全く別物です。 値が引き継がれたりするわけではありません。 ですから、Aというクラスで宣言したaという変数の値をBクラスで使いたいのならば、Bクラスに渡してあげる必要があります。 一般的に値の引渡しは、引数付きコンストラクタで値を渡すか、セッターと呼ばれる「クラスに値を設定するメソッド」を宣言することで渡します。
お礼
回答ありがとうございます。 値の引き渡しを行なうときは、引数付きコンストラクタ(ANo.3)でするかセッターと呼ばれるクラスに値を設定すると。。。 下にも書きましたが、テキスト等の勉強だけではあまり実にならない感じです。自分ではわかっているつもりでも、いざ使ってみようとあれこれしようとしていますが、できていないので正直ショックを受けました。PED02744さんのように、質問に対して回答できるような日が来るように、日々精進して参りたいと思います。
- PED02744
- ベストアンサー率40% (157/390)
えっと、、、やっぱり、何かそうとう根本的な所で勘違いがあるような気がしますが。。 コーディングを見ていると 「できない」と悩んでおられる内容と「ロジック」のスキルが不一致なんです。 DBアクセス等の処理はそれなりにかけているのに、 なぜ引数程度のことが「わからない」になるのか。。 これは「課題」で引数やコンストラクタについての理解を求めたい上司の方からの問題なのかな?・・と思ったりしますが、まぁいいです(笑) Zenkenkensaku zenkenkensaku1 = new Zenkenkensaku(); // メインのこれを Zenkenkensaku zenkenkensaku1 = new Zenkenkensaku(connectclose1); // にする Zenkensakuクラスに引数付きコンストラクタ追加 public Zenkensaku(ConnectClose connectclose1){ this.conn = connectclose1.getConnection(); } ConnectCloseクラスにコネクション取得メソッドを追加 public Connection getConnection(){ return this.conn; }
お礼
解答ありがとうございます。 事実、実務に触れたこともなくテキストを参考にメソッドを使ってみようと思い色々試行錯誤している状態なので、Javaのソースがおかしいところが多々あるかと思います。もう一度SJC-Pの範囲の勉強をしなおす必要がありそうで、スキルが少ないのに質問して申し訳ありませんでした。優しい回答ありがとうございます。今しているのはJavaとデータベースの知識をそれぞれテキスト等で勉強したので、それをミックスさせてみようということでJDBCアプリケーションを作成しています。JDBCの仕方は触り始めてまだ1週間ちょっとで、ソースのまねごとしかできていない状態ですが、基本をもう一度復習し、これから一人前になるべく頑張っていきます。引数、コンストラクタについて詳しく回答くださっているので、じっくり見ながら勉強します!
- PED02744
- ベストアンサー率40% (157/390)
Zenkenkensaku.javaのConnection変数connがnullのまま。 nullなのに、createStatement()メソッドを呼び出しているので、nullExceptionになる。 ってことですね。 コネクションをメインで作るのなら、Zenkenkensakuコンストラクタに渡してZenkenkensakuクラスのCOnnection変数に設定してあげないとだめですね。 メインもおかしいです。 どうして、コネクト用とクローズ用に二つコネクションがあるんですか?(^_^;) オブジェクティブな作りがわかっていないとは思いませんが、 なにかとんでもないところで勘違いをされているように思います。
補足
回答ありがとうございます。メインがおかしいのはクローズするとき ConnectClose connectclose2 = new ConnectClose(); connectclose2.Close(); ではなく、 connectclose1.Close(); とするのが正しいみたいです。ご指摘ありがとうございます。 connについてなのですが、connは接続とクローズのファイルで定義しています。ただ、使いまわせていないという状況でしょうか?(接続ユーザー名とパスは伏せてあります) ConnectClose.java //接続とクローズのファイル package DBAccess; //JDBC APIをインポート import java.sql.*; class ConnectClose { Connection conn = null; public void Connect() throws SQLException, ClassNotFoundException{ // Oracle JDBC Driverのロード Class.forName("oracle.jdbc.driver.OracleDriver"); // Oracle10gに接続 conn = DriverManager.getConnection ("jdbc:oracle:thin:@localhost:1521:ORCL", "*******", "******"); } public void Close() throws SQLException, ClassNotFoundException{ // 接続をクローズ conn.close(); } } 以上、よろしくお願いいたします。
お礼
言われて、ハっと気がつきました。確かに、設定していませんでした。 一文足すだけで実行できました。ありがとうございました。