0

理解できない問題があります。簡単だと思いますが、Google 検索と Stackoverflow 検索では問題が解決しませんでした。Javaのドキュメントも役に立ちませんでした。私は、人々が SQL ステートメントやコードで構文エラーを起こすという多くの問題を発見しました。私はコードにあると思います。これは、ユーザーが独自の検索情報 (数値) を入力できるクエリによって、データベースから情報を取得することです。

コードは次のとおりです。

    /*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package dbConnection;

import data.Mail;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import view.SelectionScreenCRA;

/**
 *
 * @author vm
 */
public class dbConnect {

    public static Connection getConnection() {
        String driver = "sun.jdbc.odbc.JdbcOdbcDriver";
        String url = "jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=C:\\Users\\Jeroen Veldhuijzen\\locaties.mdb;";
        String username = "";
        String password = "";

        try {
            Class.forName(driver);
            return DriverManager.getConnection(url, "", "");

        } catch (Exception ex) {
            Logger.getLogger(dbConnect.class.getName()).log(Level.SEVERE, null, ex);
            System.out.println("\nError: " + ex.toString() + ex.getMessage());

        }
        return null;
    }

    public static ArrayList<dbConnect> executeQuery(int cra) {


         ArrayList<dbConnect> locatie = new ArrayList<dbConnect>();

        Mail mail = new Mail();
        try{
        Connection conn = getConnection();
        PreparedStatement pst = conn.prepareStatement(
                "SELECT Locatiegegevens.[Locatiegegevens], "
                + "Locatiegegevens.[ISP - Straatnaam], "
                + "Locatiegegevens.[ISP - Huisnummer],"
                + " Locatiegegevens.[ISP - Postcode], "
                + "Locatiegegevens.[ISP - Plaatsnaam], "
                + "Locatiegegevens.[G4S - Transportcode] "
                + "FROM Locatiegegevens "
                + "WHERE Locatiegegevens.[Locatiegegevens] = '?';");


        pst.setInt(1, cra);
        pst.execute();

        pst.close();
        conn.close();

        }catch (Exception e){
            System.out.println("ERRROOOOR");

            System.out.println(e.getMessage());
            System.out.println(e.getClass());
            Logger.getLogger(dbConnect.class.getName()).log(Level.SEVERE, null, e);

        }
        return locatie;

    }

}

int cra は次のように設定されます。

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                         
    dbConnect dbc = new dbConnect();
    dbConnect.executeQuery(Integer.parseInt(getCRA().getText()));        
}

cra は String として取得され、executeQuery コマンドに渡されるときに int に解析されます。cra int を検索すると、テキスト ボックスに入力された int 9501 が返されます。しかし、ボタン jButton1 を押してクエリを実行すると、null エラーが発生します。

null

class java.lang.NullPointerException
aug 09, 2012 12:43:04 PM dbConnection.dbConnect executeQuery
SEVERE: null
java.lang.NullPointerException
    at sun.jdbc.odbc.JdbcOdbcPreparedStatement.clearParameter(JdbcOdbcPreparedStatement.java:1022)
    at sun.jdbc.odbc.JdbcOdbcPreparedStatement.setInt(JdbcOdbcPreparedStatement.java:526)
    at dbConnection.dbConnect.executeQuery(dbConnect.java:62)
    at view.SelectionScreenCRA.jButton1ActionPerformed(SelectionScreenCRA.java:502)
    at view.SelectionScreenCRA.access$900(SelectionScreenCRA.java:29)
    at view.SelectionScreenCRA$11.actionPerformed(SelectionScreenCRA.java:333)
    at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2018)
    at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2341)
    at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
    at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
    at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
    at java.awt.Component.processMouseEvent(Component.java:6504)
    at javax.swing.JComponent.processMouseEvent(JComponent.java:3321)
    at java.awt.Component.processEvent(Component.java:6269)
    at java.awt.Container.processEvent(Container.java:2229)
    at java.awt.Component.dispatchEventImpl(Component.java:4860)
    at java.awt.Container.dispatchEventImpl(Container.java:2287)
    at java.awt.Component.dispatchEvent(Component.java:4686)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832)
    at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4492)
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422)
    at java.awt.Container.dispatchEventImpl(Container.java:2273)
    at java.awt.Window.dispatchEventImpl(Window.java:2713)
    at java.awt.Component.dispatchEvent(Component.java:4686)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:707)
    at java.awt.EventQueue.access$000(EventQueue.java:101)
    at java.awt.EventQueue$3.run(EventQueue.java:666)
    at java.awt.EventQueue$3.run(EventQueue.java:664)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
    at java.awt.EventQueue$4.run(EventQueue.java:680)
    at java.awt.EventQueue$4.run(EventQueue.java:678)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:677)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:211)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:90)

私を正しい方向に向けることができる人はいますか?

4

2 に答える 2

0

Miko が問題を特定しました。彼が言うように、クエリ文字列でパラメーターのプレースホルダー (?) を引用符で囲んではいけません。種類は問いません。

これは、実際に何が起こっているかを説明するためのものです...そしてなぜNPEになるのか.

パラメータ マーカーを引用符で囲むと、実際には SQL 文字列を記述しています。がcreatePreparedStatmentクエリ文字列を分析すると、マーカーがまったく見つかりません。それは問題ありません1構文の観点からは ... しかし、これは、クエリが意図した意味を持っていないことを意味します。

すると少し濁ります。(存在しない) パラメータ 1を試行しているときに NPE が発生しsetます。しかし、スタック トレースを見ると、実際には というメソッドにありclearParameterます。MS JDBC ドライバーのソース コードは調べていませんが、準備済みステートメント パーサーがプレースホルダー パラメーターの配列を作成していると推測されます。しかし、何も見つからない場合は、わざわざ配列を割り当てません。通常は無害ですが、プレースホルダーの値を設定しようとすると、コードが適切にチェックされず、誤って NPE が生成されているように見えます。

いずれにせよ、この状況で NPE をスローすることは、JDBC ドライバー側の動作として不適切です。私はそれをバグと呼んでいます!

アップデート

ここでソース コードを見つけましたが、私の仮説は基本的に正しかったのです。ただし、これは Microsoft のコードではなく、古い Sun のコードです。(それはパッケージ名から明らかなはずです...当たり前!)

問題はそれboundParamsですnull。2727 行を見ると、プレースホルダーの数が 0 より大きい場合にのみ初期化されます。バグ!


1 - 実際には問題ありません。この場合、「文字列」が列の型と一致しないため、SQL エラーが発生する可能性が高いためです。しかし、その分析は、クエリがデータベース サーバーに到達したときに実行されます。多くの JDBC ドライバーでは、実際にクエリを初めて実行するまで、これは行われません。

于 2013-06-22T01:14:21.847 に答える
0

パラメーター マーカー (?) を囲む引用符を削除します。また、クエリ文字列の末尾にあるセミコロンは必要ありません。

"WHERE Locatiegegevens.[Locatiegegevens] = ?");
于 2012-08-09T11:44:55.890 に答える