0

Overview: Trying to connect to a MS Access DB to return a result set into a jtable.

Issue: java null pointer exception

Code:

package sundata;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class Database {

public String strMIGID;
public String strEBID;
public String strSUN;
public String[][] objIDList;

//CONNECTION INFO
private Connection con;
private String strDBCon="jdbc:ucanaccess://C:/Users/Luke/Documents/MainDB.mdb";
public String strEXMessage;

public int CreateConnection(){
    try{
        Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
        con = DriverManager.getConnection(strDBCon);

        return 1;
    }catch(Exception ex){
        ex.printStackTrace();
        strEXMessage=ex.getMessage();
        return 2;
    }

}

public int CloseConnection(){
    try{
        con.close();
        return 1;
    }catch(Exception ex){
        ex.printStackTrace();
        strEXMessage=ex.getMessage();
        return 2;
    }

}

public int GetMIGIDRecord(String strMIGIDRef){
    try{
        System.out.println("Connecting to database using MIGID");

        String strSQLString = "Select * from tblSuppliersData where Supplier1 = ?";
        PreparedStatement preStatement = con.prepareStatement(strSQLString, ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);

        //SETTING FIRST CONDITION OF PREPARED STATEMENT IE ?
        preStatement.setString(1, strMIGIDRef);

        //EXECUTE QUERY
        preStatement.executeQuery();

        //RETURNS QUERY RESULTS INTO RESULT SET
        ResultSet rs = preStatement.getResultSet();

        //CHECK TO MAKE SURE SOME RECORDS ARE RETURNED
        rs.last();
        //IF CHECKS TO MAKE SURE RECORDS
        if(rs.getRow()==0){
            rs.close();      
            preStatement.close();
            return 3;
        }
        //RECORDS NUMBER OF RECORDS
        int iNoRecords = rs.getRow();

        //CREATING 2D ARRAY WITH NO RECORDS (ROWS) AND TWO COLUMNS
        String strTempdata[][] = new String [iNoRecords][3];

        //MOVES BACK TO BEFORE FIRST RECORD
        rs.beforeFirst();

        //TRANSPOSES RS IN TO ARRAY
        int i = 0;
        while (rs.next()){
            strTempdata[i][0]= rs.getString("MIGID");
            strTempdata[i][1]= rs.getString("EBID");
            strTempdata[i][2]= rs.getString("SUN");
            i++;
        }
        objIDList = strTempdata;
        //CLOSES CONNECTIONS
        rs.close();
        preStatement.close();

        System.out.println("Connection complete");

        return 1;
    }catch(Exception ex){
        ex.printStackTrace();
        strEXMessage=ex.getMessage();
        return 2;
    }
}

I have a form that grabs the strMIGIDREF which I can paste code from if needs be, but I think it's not the issue here.

This is the error I'm getting, I've pasted the first bit and can paste more if required.

Connecting to database using MIGID
java.lang.NullPointerException
at sundata.Database.GetMIGIDRecord(Database.java:63)
at sundata.MainForm.MIGIDSearch(MainForm.java:141)
at sundata.MainForm.jmenuMIGIDSearchActionPerformed(MainForm.java:337)
at sundata.MainForm.access$000(MainForm.java:6)
at sundata.MainForm$1.actionPerformed(MainForm.java:58)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2018)

Line 63 is

//CHECK TO MAKE SURE SOME RECORDS ARE RETURNED
rs.last();

I have tried a number of solutions I've found on Google and no joy as of yet. I have tried a test bit of code that checks connections and such and that seemed to work fine it's just when I'm trying use preparedstatement it seems to go a miss. ResultSet rs = preStatement.getResultSet(); just keeps saying it's value is null and so is getMaxRows.

I'm using Netbeans IDE 7.4 and JAVA SE SDK 7

Gord Thompson
  • 116,920
  • 32
  • 215
  • 418
ppw
  • 155
  • 4
  • 17

1 Answers1

3

You are getting a NullPointerException because you are mis-using the executeQuery method:

//EXECUTE QUERY
preStatement.executeQuery();

//RETURNS QUERY RESULTS INTO RESULT SET
ResultSet rs = preStatement.getResultSet();

The first line of code executes the SQL query and returns a ResultSet object, which you simply discard (because you don't assign it to anything). The second line of code attempts to retrieve the ResultSet for the PreparedStatement, but it has already been retrieved (and discarded) by the previous line, so getResultSet returns null.

Instead, you should simply do

ResultSet rs = preStatement.executeQuery();

Additional notes:

  1. Omit the Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); statement because (1) It is irrelevant: UCanAccess does not use ODBC, and (2) Class.forName statements are almost never required any more (and UCanAccess doesn't need one at all).

  2. Don't use rs.last() to test if rows were returned. Instead, simply call rs.next() immediately after the ResultSet is returned. If rs.next() returns true then the ResultSet contains rows (and you are now pointing at the first one). If rs.next() returns false then no rows were returned. rs.last() followed by rs.beforeFirst() will not work correctly with the default ResultSet type, which is ResultSet.TYPE_FORWARD_ONLY.

Gord Thompson
  • 116,920
  • 32
  • 215
  • 418
  • Thanks for the comprehensive answer Gord! – ppw May 23 '14 at 08:05
  • The first part works perfectly! The part about the rs.last() and rs.beforefirst() I tried your suggestion but I was getting errors further down when I was transferring the rs into an array, now I'm sure again it is me doing something wrong somewhere else in the code, but to get around it I used ResultSet.TYPE_SCROLL_INSENSITIVE then rs.last and rs.beforeFirst. Feel free to take a look at the rest of the code and see if you can see where else I'm going wrong with the array, but there's no major issues now though. Many thanks again! – ppw May 23 '14 at 08:25