Null Pointer Exception in Prepared Statement [duplicate] - java

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 4 years ago.
I ran in to a problem while trying to get data from my sql server where they give a null point exception at prepared statement. I'm sure this must be a noob question but please do help :)
this is the method i'm calling
public void notification(){
int MachCode = 1721;
try{
String sql ="Select TimeOn from PRODUCTIONS_MONITOR where MachCode='"+MachCode+"'";
pst = con.prepareStatement(sql);
rs = pst.executeQuery();
while(rs.next()){
arrCount.add(rs.getInt(1));
}
for(int i=0;i<arrCount.size();i++){
Count = Count + arrCount.get(i);
}
if(Count % 10 == 0){
System.out.println("Time = " + Count);
}
}catch(SQLException e){
e.printStackTrace();
}
}
and here is my db connection
public static Connection ConnecrDb() {
try {
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
Connection con = DriverManager.getConnection("jdbc:sqlserver://10.228.59.2:1433;databaseName=dbNautilus;user=SA;password=KreedaIntimo#2017;");
System.out.println("Connected to database !");
} catch (SQLException sqle) {
System.out.println("Sql Exception :" + sqle.getMessage());
} catch (ClassNotFoundException e) {
System.out.println("Class Not Found Exception :" + e.getMessage());
}
return null;
}

Your ConnecrDb() method assigns the new Connection object to a local variable named con, and then never use it.
The method then returns null.
You didn't show how to method was called, but it really doesn't matter, because the con field used by notification() method is either unassigned (and hence null), or assigned the null return value from ConnecrDb(), so it is null either way.
Given that, why are you confused the value is null and causes a NullPointerException?
Other general comment about your code:
If MachCode is an integer, then why are you quoting it in SQL, i.e. why where MachCode='"+MachCode+"'"; and not where MachCode="+MachCode;?
If you're using PreparedStatement, why not use ? parameter markers, as they are intended to be used?
You should use try-with-resources when using JDBC.
Java naming convention is for variable names to start with lowercase letter.
Your code should be:
int machCode = 1721;
String sql = "select TimeOn from PRODUCTIONS_MONITOR where MachCode = ?";
try (PreparedStatement pst = con.prepareStatement(sql)) {
pst.setInt(1, machCode);
try (ResultSet rs = pst.executeQuery()) {
while (rs.next()) {
arrCount.add(rs.getInt(1));
}
}
}
// rest of code here

Related

JDBC ResultSet closed in Java after several iterations

I am having a problem with a ResultSet being closed. What confuses me is that it works for a portion of the data and then closes. At first I thought it might be because of connection timeout but that doesn't seem the case.
This portion of the program pertains to comparing an .xlsx workbook to an already present SQL database and for lack of a better term merges/updates it.
First, in my CompareDatabase class I am calling a search function that searches an SQLite database for a specific string every 6 iterations.
int columnCount = 6;
dataPoint = dataPoint.replaceAll("Detail", "");
String[] temp = dataPoint.trim().split("\\s+");
System.out.println(Arrays.toString(temp));
for (String tempDataPoint : temp) {
if ( columnCount == 6) {
System.out.println(search(tempDataPoint, connection));
}
columnCount = 0;
} else {
columnCount++;
}
}
This search function (also in the CompareDatabase class is then supposed to search for the value and return a String (was originally a Boolean but I wanted to see the output).
private String search (String searchValue, Connection connection) throws SQLException {
PreparedStatement pStatement = null;
pStatement = connection.prepareStatement("SELECT * FROM lotdatabase where (Vehicle) = (?)");
pStatement.setString(1, searchValue);
try (ResultSet resultSet = pStatement.executeQuery()){
return resultSet.getString(1);
}finally {
close(pStatement);
}
}
At the end you can see that the PreparedStatement is closed. The ResultSet should also be closed automatically (I read somewhere) but JDBC could possibly be being unreliable.
The Connection however is still open as it will be searching some 200+ strings and opening and closing that many times did not seem like a good idea.
These functions are called by my main class here:
One is commented out since it will error out because of primary key violation.
public static void main(String[] args) {
SQLDatabase sqlDatabase = new SQLDatabase();
//sqlDatabase.convertToSQL("Database1.xlsx");
sqlDatabase.compare("Database2.xlsx");
}
I have a suspicion that I am going about a bunch of this wrong (on the aspect of managing connections an such) and I would appreciate a reference to where I can learn to do it properly.
Also, being that PreparedStatement can only handle one ResultSet I don't see that being my issue since I close it every iteration in the for loop.
If more code or explanation is required please let me know and I will do my best to assist.
Thank you for taking the time to read this.
So after a bit more Googling and sleeping on it here is what worked for me.
The search function in compareDatabase changed to this:
private Boolean search (String searchValue, Connection connection) {
PreparedStatement ps = null;
try {
ps = connection.prepareStatement("SELECT * FROM lotdatabase where " +
"(Vehicle) = (?)");
ps.setString(1, searchValue);
ResultSet resultSet = ps.executeQuery();
//The following if statement checks if the ResultSet is empty.
if (!resultSet.next()){
resultSet.close();
ps.close();
return false;
}else{
resultSet.close();
ps.close();
return true;
}
} catch (SQLException e) {
e.printStackTrace();
}
return false;
}
And in the other function within compareDatabase I call the search function like this:
if (search(tempDataPoint, connection)) {
System.out.println("MATCH FOUND: " + tempDataPoint);
}else {
System.out.println("NOT FOUND: " + tempDataPoint);
}
This allows me to check the ResultSet and also be sure that it is closed.

different results if PreparedStatement is used as resource in try block

Some behaviour I don't understand.
I have a running script like:
ResultSet res = null;
String cmd = new String("SELECT value FROM " +pDS.getValueTableName() + " WHERE itemID=? and propertyID=? ORDER BY checkpointID DESC");
PreparedStatement pstmt= dbconn.prepareStatement(cmd) ;
pstmt.setLong(1,itemID);
pstmt.setLong(2,pDS.getPropertyID());
try {
res = pstmt.executeQuery();
}
catch(Exception e)
{
throw(e);
}
if (!res.next())
{
// other code
}
Here i get the expected values res.next()=true.
No exception is thrown.
I wanted to refactor the code, and use the Autoclose funtionalty of the try block, like:
ResultSet res = null;
String cmd = new String("SELECT value FROM " +pDS.getValueTableName() + " WHERE itemID=? and propertyID=? ORDER BY checkpointID DESC");
try (PreparedStatement pstmt= dbconn.prepareStatement(cmd) ){
pstmt.setLong(1,itemID);
pstmt.setLong(2,pDS.getPropertyID());
res = pstmt.executeQuery();
}
catch(Exception e)
{
LOGGER.error("Error at getLatestPropertyResultSet",e);
throw(e);
}
if (!res.next())
{
// other code
}
However now res.next()=false. The resultset itselve is intialized res!=null.
Why did this modification change the behaviour of the script?
Without seeing where you call res.next() I can only assume that the try-with-resource is doing exactly as advertised and closing the prepared statement once you leave the try block and thus the result is "closed" with it.
update: based on your edit my suspicions are confirmed. You need to move any work related to the resource inside the try block.

ResultSet is Closed

Following is my Table Definition:
create Table alarms(
alarmId int primary key identity(1,1),
alarmDate varchar(50) not null,
alarmText varchar(50) not null,
alarmStatus varchar(10) Check (alarmStatus in(-1, 0, 1)) Default 0
);
Secondly here are some of my methods i'm using:
public void restartDatabase(){
try{
Class.forName(Settings.getDatabaseDriver());
connection = DriverManager.getConnection( Settings.getJdbcUrl() );
statement = connection.createStatement();
}
catch(Exception e){
e.printStackTrace();
}
}
public ResultSet executeQuery(String query){
ResultSet result = null;
try {
result = statement.executeQuery(query);
} catch (SQLException e) {
e.printStackTrace();
}
return result;
}
public void closeDatabase() {
try {
if ((statement != null) && (connection != null)) {
statement.close();
connection.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
What i want to do is to get all the alarmId's from the table where date is equal to the given date and then against each alarmId i want to update its status to given status:
public static void updateAlarmStatus(int status) {
ResultSet rs = null;
database.restartDatabase();
try {
rs = database
.executeQuery("Select alarmId from alarms where alarmDate = '"
+ Alarm.getFormattedDateTime(DateFormat.FULL,
DateFormat.SHORT) + "'");
while (rs.next()) {
database.executeUpdate("update alarms set alarmStatus = '"+status+"' where alarmId = '"+rs.getString("alarmId")+"'");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
database.closeDatabase();
}
}
But it generates the Error that Result Set is Closed.
I Goggled it and came to know that a result set automatically closes when we try to execute another query inside it
and it needs to restart the connection.
i tried calling restartDatabase() method that is creating new connection but still getting the same error.
I'm guessing executeUpdate uses the same instance variable for its Statement as the query uses. When you create a new Statement and assign it to the variable, nothing is referring to the old one, so it gets cut loose and becomes subject to garbage-collection. During garbage collection the statement's finalizer is invoked, closing it. Closing the statement makes the ResultSet it created close as well.
You shouldn't be sharing these Statement variables between different queries and updates. The statement should be a local variable and not a member of an object instance.
Also, result Sets should always be local variables, they shouldn't be passed outside the method where they're created. The resultSet is a reference to a cursor, it doesn't actually hold any data. Always have your code read from the resultSet and populate some data structure with the results, then return the data structure.
You can also select and change all alarmIds at once:
rs = database.
executeQuery("Select group_concat(distinct alarmId) as alarmIds from alarms group by alarmDate having alarmDate = '"
+ Alarm.getFormattedDateTime(DateFormat.FULL,
DateFormat.SHORT) + "'");
while (rs.next()) { // there will be only one result
database.executeUpdate("update alarms set alarmStatus = '"+status+"' where alarmId in ("+rs.getString("alarmIds")+")");
}

Java prepared statement in try-with-resources not working [duplicate]

This question already has answers here:
How should I use try-with-resources with JDBC?
(5 answers)
Closed 8 years ago.
Yesterday multiple people on Stack recommended using try-with-resources. I am doing this for all my database operations now. Today I wanted to change Statement to PreparedStatement to make the queries more secure. But when I try to use a prepared statement in try-with-resources I keep getting errors like 'identifier expected' or ';' or ')'.
What am I doing wrong? Or isnt this possible? This is my code:
try (Connection conn = DriverManager.getConnection(DBURL, DBUSER, DBPASS);
PreparedStatement stmt = conn.prepareStatement("SELECT id FROM users WHERE id = ? LIMIT 1");
stmt.setInt(1, user);
ResultSet rs = stmt.executeQuery()) {
// if no record found
if(!rs.isBeforeFirst()) {
return false;
}
// if record found
else {
return true;
}
} catch (SQLException e) {
// log error but dont do anything, maybe later
String error = "SQLException: " + e.getMessage() + "\nSQLState: " + e.getSQLState() + "\nVendorError: " + e.getErrorCode();
return false;
}
A try-with-resource statement is used to declare (Autoclosable) resources. Connection, PreparedStatement and ResultSet are Autoclosable, so that's fine.
But stmt.setInt(1, user) is NOT a resource, but a simple statement. You cannot have simple statements (that are no resource declarations) within a try-with-resource statement!
Solution: Create multiple try-with-resource statements!
try (Connection conn = DriverManager.getConnection(DBURL, DBUSER, DBPASS)) {
executeStatement(conn);
} catch (SQLException e) {
// log error but dont do anything, maybe later
String error = "SQLException: " + e.getMessage() + "\nSQLState: " + e.getSQLState() + "\nVendorError: " + e.getErrorCode();
return false;
}
private void executeStatement(Connection con) throws SQLException {
try (PreparedStatement stmt = conn.prepareStatement("SELECT id FROM users WHERE id=? LIMIT 1")) {
stmt.setInt(1, user);
try (ResultSet rs = stmt.executeQuery()) {
// process result
}
}
}
(Please note that technically it is not required to put the execution of the SQL statement into a separate method as I did. It also works if both, opening the connection and creating the PreparedStatement are within the same try-with-resource statement. I just consider it good practice to separate connection management stuff from the rest of the code).
try this code:
try (Connection conn = DriverManager.getConnection(DBURL, DBUSER, DBPASS)) {
PreparedStatement stmt = conn.prepareStatement("SELECT id FROM users WHERE id = ? LIMIT 1");
stmt.setInt(1, user);
ResultSet rs = pstmt.executeQuery())
// if no record found
if(!rs.isBeforeFirst()) {
return false;
}
// if record found
else {
return true;
}
} catch (SQLException e) {
// log error but dont do anything, maybe later
String error = "SQLException: " + e.getMessage() + "\nSQLState: " + e.getSQLState() + "\nVendorError: " + e.getErrorCode();
return false;
}
note that here, resource is your Connection and you have to use it in the try block ()
Move
stmt.setInt(1, user);
ResultSet rs = stmt.executeQuery()
...within the try{ /*HERE*/ }
This is because stmt is the resource being created try (/*HERE*/) {} to be used try{ /*HERE*/ }
Try-with-resources
try (/*Create resources in here such as conn and stmt*/)
{
//Use the resources created above such as stmt
}
The point being that everything created in the resource creation block implements AutoClosable and when the try block is exited, close() is called on them all.
In your code stmt.setInt(1, user); is not an AutoCloseable resource, hence the problem.

ResultSet.getInt() ERROR [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
so I'm trying to connect to a database using java.. there's a problem at a function I wrote getOutSymptoms.
Here's the code
package database_console;
import java.sql.*;
public class DBConnect {
private Connection con;
private Statement st;
private ResultSet rs;
public DBConnect(){
try {
Class.forName("com.mysql.jdbc.Driver");
try {
con = DriverManager.getConnection("jdbc:mysql://localhost:3306/users", "root", "admin");
st = con.createStatement();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public int getOutSymptoms(int userID) throws SQLException{
String query = "SELECT `user`.`out_symptoms` FROM user WHERE (`user`.`id` =" + userID + ")";
rs = st.executeQuery(query);
int out_symptoms_value = rs.getInt("out_symptoms");
st.close();
return out_symptoms_value;
}
the error is at the getOutSymptoms function, at the line:
int out_symptoms_value = rs.getInt("out_symptoms");
why is that? and how can I fix it?
thank u so much.
You need to iterate through your result set in order to get the returned rows. When you first get your new ResultSet, it's not pointing to any particular row (its pointer is set to a row before first) and you need to call rs.next() method at least once to get to the actual results.
If you know there can be only one result you can do something like this:
if (rs.next()) {
int out_symptoms_value = rs.getInt("out_symptoms");
//do other stuff
} else {
//query returned no results
}
If you expect to have more than one row returned, then you can do this:
while(rs.next()) {
int out_symptoms_value = rs.getInt("out_symptoms");
//do the rest of processing
}
TLDR: You need to call rs.next() at least once to get to the actual results.
In order to start using a ResultSet, you must call the next() method. Although you haven't stated the exact error, you will definitely run into this problem unless it is added before you call getInt().
http://docs.oracle.com/javase/tutorial/jdbc/basics/retrieving.html
you need to iterate through the resultSet object using rs.next() to get the value. resultSet doesn't point to the actual row but when you call rs.next() it points to first result.
while(rs.next(){
int d = rs.getInt(" ");
}
rs.next() returns a boolean value , incase nothing is returned the loop will not execute & you will not get an Exception at runtime.
You have already passed the database name in connection string so change this
String query = "SELECT `user`.`out_symptoms` FROM user WHERE (`user`.`id` =" + userID + ")";
to
String query = "SELECT out_symptoms FROM tableName WHERE id =" + userID;
Then just iterate over the obtained ResultSet like this
while(rs.next()) {
int out_symptoms_value = rs.getInt("out_symptoms");
}
Moreover its good to use PreparedStatement instead of Statement which cna prevent you from sql injection

Categories

Resources