簡體   English   中英

java Prepared語句因空錯誤而失敗

[英]java Prepared Statement fails on null error

我有一個我不知道的問題,我敢肯定這很容易,但是我的Google搜索和Stackoverflow搜索沒有讓我到達那里。 Java文檔都沒有幫助。 我發現很多人在SQL語句或代碼中出現語法錯誤的問題。 我認為我的是在代碼中。 它是關於通過查詢從數據庫中獲取一些信息的,用戶可以在其中填寫自己的搜索信息(數字)。

這是代碼:(我嘗試了很多事情,所以可能我的代碼不再是最好的了。而且我對Java還是陌生的,因此請考慮一下。)

    /*
 * 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將作為字符串檢索,然后在將其傳遞給executeQuery命令時解析為int。 如果我將cra int發出,它將為我提供int 9501,該int填寫在文本框中。 但是,如果我通過按下按鈕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)

有沒有人可以指出我正確的方向?

刪除參數標記(?)周圍的引號。 另外,不需要在查詢字符串末尾使用分號:

"WHERE Locatiegegevens.[Locatiegegevens] = ?");

Micko已確定問題所在。 正如他所說, 永遠不要在查詢字符串中的參數占位符(?) 前后加上引號。 類型是什么都沒關系。

這僅僅是為了解釋實際發生的事情……以及獲得NPE的原因。

如果在參數標記周圍加上引號,則實際上是在編寫SQL字符串。 createPreparedStatment分析查詢字符串時,它根本找不到任何標記。 這是從語法的角度來看OK 1 ...但它意味着查詢並不意味着你想要它的意思。

然后變得有點模糊。 NPE在嘗試set (不存在)參數1時發生。但是,如果您查看stacktrace,它實際上是在名為clearParameter的方法中。 我沒有尋找MS JDBC驅動程序的源代碼,但我的猜測是,准備好的語句解析器會創建一個占位符參數數組。 但是,如果找不到任何內容,則不必分配數組。 這通常是無害的……但是,如果您隨后嘗試設置占位符的值,則表明代碼未正確檢查,並且偶然生成了NPE。

無論哪種方式,在這種情況下拋出NPE都是JDBC驅動程序方面的不良行為。 我稱它為Bug!

更新

我在這里找到了源代碼並且我的假設基本上是正確的…… 只是這是舊的Sun代碼,而不是Microsoft代碼。 (從程序包名稱中應該很明顯……...!)

問題是boundParamsnull 如果查看第2727行,則僅當占位符的數量大於零時才初始化它。 臭蟲!


1-實際上,這不行,因為在這種情況下,您很可能會收到SQL錯誤,因為“字符串”與列的類型不匹配。 但是,該分析是在查詢到達數據庫服務器時執行的……對於許多JDBC驅動程序,直到您第一次真正執行查詢時,這種情況才會發生。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM