2013-05-31 184 views
0

有沒有人請賜教,爲什麼準備語句返回null?下面是查詢數據庫的代碼:這裏JDBC PreparedStatement拋出NullPointerException

package beans; 
import java.sql.*; 
public class ConnectToDB { 
private Connection connect; 

private final String url = "jdbc:mysql://localhost/"; 
private final String DBuser = "root"; 
private final String DBpass = "root"; 
private final String DBname = "reservation"; 

private final String Driver = "com.mysql.jdbc.Driver"; 
public ConnectToDB(){ 
    try{ 
     Class.forName(this.Driver); 
     this.connect = DriverManager.getConnection(this.url+this.DBname, this.DBuser, this.DBpass); 
    }catch( ClassNotFoundException | SQLException e){ e.printStackTrace(); } 
} 
public Connection getConnection(){ 
    return this.connect; 
} 

private String get_user_info(String username,int index){ 
    /* 
    * user_info[0] = user_id; 
    * user_info[1] = username; 
    * user_info[2] = password; 
    * user_info[3] = firstname; 
    * user_info[4] = middle_name; 
    * user_info[5] = lastname; 
    * user_info[6] = client_rights; 
    * 
    */ 
    String user_info[] = new String[7]; 
    PreparedStatement pstmt = null; 
    ResultSet rset = null; 
    String query = null; 
    try{ 
     query = "Select * from user where username = ?"; 
     pstmt = this.connect.prepareStatement(query); 
     pstmt.setString(1, username); 
     rset = pstmt.executeQuery(); 
     while(rset.next()){ 
      int user_id = rset.getInt("user_id"); 
      user_info[0] = String.valueOf(user_id); 
      user_info[1] = rset.getString("username"); 
      user_info[2] = rset.getString("password"); 
      user_info[3] = rset.getString("firstname"); 
      user_info[4] = rset.getString("middle_name"); 
      user_info[5] = rset.getString("lastname"); 
      user_info[6] = rset.getString("user_rights"); 
     } 
    }catch(SQLException e){ e.printStackTrace(); } 
    finally{ 
     try{ 
      pstmt.close(); 
      rset.close(); 
     }catch(SQLException e){ e.printStackTrace(); } 
    } 
    return user_info[index]; 
} 

public int getUserId(String username){ 
    String user_id_from_db = get_user_info(username, 0); 
    int user_id = Integer.parseInt(user_id_from_db); 
    return user_id; 
} 

public String getUsername(String username){ return get_user_info(username, 1); } 
public String getPassword(String username){ return get_user_info(username, 2); } 
public String getFirstname(String username){ return get_user_info(username, 3); } 
public String getMiddlename(String username){ return get_user_info(username, 4); } 
public String getLastname(String username){ return get_user_info(username, 5); } 
public String getUserRights(String username){ return get_user_info(username, 6); } 

public boolean userExists(String username){ 
    boolean queryStatus = false; 
    if(username.equalsIgnoreCase(getUsername(username))) 
     queryStatus = true; 
    else 
     queryStatus = false; 
    return queryStatus; 
} 
} 

然後是調用查詢代碼:

<jsp:useBean id="user" class="beans.ConnectToDB" scope="session" /> 
<jsp:useBean id="aes" class="beans.AES" scope="session" /> 

String getUsername = request.getParameter("username"); 
     String getPassword = request.getParameter("password"); 

     final String passphrase = "#[email protected]#";  
     byte[] password_byte = getPassword.getBytes(); 
     byte[] passphrase_byte = passphrase.getBytes(); 
     byte[] encrypt_password = aes.encrypt(password_byte, passphrase_byte);  

     if((getUsername != null && !getUsername.isEmpty()) || (getPassword != null && !getPassword.isEmpty())){ 
      String username_from_db = user.getUsername(getUsername); 
      String password_from_db = user.getPassword(getUsername); 

      byte[] pass_db_byte = password_from_db.getBytes(); 
      byte[] encrypted_pass_db = aes.encrypt(pass_db_byte, passphrase_byte); 

      if(getUsername.equalsIgnoreCase(username_from_db) && encrypt_password.equals(encrypted_pass_db)){ 
       response.sendRedirect("home_page.jsp"); 
      } 
     } 
     else{ response.sendRedirect("index.jsp"); } 

當我打電話getUsername(String username)方法返回null這裏是拋出的異常:

org.apache.jasper.JasperException: An exception occurred processing JSP page /authenticate_user.jsp at line 29 
26:    byte[] encrypt_password = aes.encrypt(password_byte, passphrase_byte);  
27:    
28:    if((getUsername != null && !getUsername.isEmpty()) || (getPassword != null && !getPassword.isEmpty())){ 
29:     String username_from_db = user.getUsername(getUsername); 
30:     String password_from_db = user.getPassword(getUsername); 
31: 
32:     byte[] pass_db_byte = password_from_db.getBytes(); 


Stacktrace: 
org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:568) 
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:470) 
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:390) 
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334) 
javax.servlet.http.HttpServlet.service(HttpServlet.java:728) 

root cause 

java.lang.NullPointerException 
beans.ConnectToDB.get_user_info(ConnectToDB.java:61) 
beans.ConnectToDB.getUsername(ConnectToDB.java:72) 
org.apache.jsp.authenticate_005fuser_jsp._jspService(authenticate_005fuser_jsp.java:110) 
org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70) 
javax.servlet.http.HttpServlet.service(HttpServlet.java:728) 
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:432) 
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:390) 
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334) 
javax.servlet.http.HttpServlet.service(HttpServlet.java:728) 
+1

這是線61?另外,JSP並不需要理解問題(恕我直言) – SJuan76

+0

第61行是get_user_info方法中finally塊中的rset.close()。 – tonix15

回答

1

您發佈的東西太多了。

所有你需要的是這樣的:

beans.ConnectToDB.get_user_info(ConnectToDB.java:61) 

在文本編輯器打開ConnectToDB.java,得到了61行,並檢查在該行的所有對象的引用。其中之一爲空,因爲您沒有正確初始化它,或者假設它在獲得它時總是非空。找出哪一個並正確地初始化它。問題解決了。

我不認爲這是一個好的解決方案。如果你有JSP,你有一個servlet/JSP引擎,它應該有一個JNDI數據庫連接池和命名服務。您應該設置並將數據庫連接參數外部化。他們不屬於你的代碼。游泳池將比您更好地管理連接。

您還沒有正確關閉您的資源。它們應該在finally塊中以與創建相反的順序關閉,幷包裝在單獨的try/catch塊中。我會寫一個可以調用的靜態實用程序方法。

package persistence; 

public class DatabaseUtils { 
    private DatabaseUtils() {} 

    // Similar for ResultSet and Connection 
    public static void close(Statement st) { 
     try { 
      if (st != null) { 
       st.close(); 
      } 
     } catch (Exception e) { 
      // Log the exception 
     } 
    } 
} 
+0

所以你說我會改變我的數據庫連接到一個池連接?喜歡這個? [Pooled Connection](http://dev.mysql.com/doc/refman/5.1/en/connector-j-usagenotes-j2ee-concepts-connection-pooling.html) – tonix15

+0

你可能會那樣做,但這不是你的直接問題。 – duffymo

+1

如果您使用Java 7,請使用try-with-resources,作爲求解器說。如果您使用Java 6或更低版本,請保存一些代碼並使用commons-db的'DbUtils.closeQuietly()'方法。另外,即使加密,看起來您仍將密碼存儲在數據庫中。這使您的應用程序易受字典攻擊。大多數用戶選擇糟糕的密碼,如「密碼」,攻擊者可以使用它來闖入系統。使用* salting *和* hashing *。安全指南可以解釋這些條款。您不想將密碼存儲在用戶對象中。 –

0

您發現的異常是由以前的異常引起的。拋出一個異常在try/catch塊的第一行:

pstmt = this.connect.prepareStatement(query); 
    pstmt.setString(1, username); 
    rset = pstmt.executeQuery(); 

因此,沒有值設置爲rsetfinally塊之前開始執行,而當你試圖用一個空值一種嶄新的工作異常。更改您的catch以捕獲所有例外情況,您將找到根本原因。

過程中,然後在一個finallycatch塊做工作的時候,記住,如果異常被拋出,則不能在try塊中的所有代碼將被執行,所以也許一些變量沒有定義。

請注意,如果您使用的是Java 7,你有可用的try with resourceshttp://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html

此外,Exception thrown in catch and finally clause

+0

[executeQuery()](http://docs.oracle.com/javase/1.4.2/docs/api/java/sql/PreparedStatement.html#executeUpdate())根據此api executeQuery()必須插入更新或刪除,我使用select查詢,這就是爲什麼它返回null? – tonix15

相關問題