Unable to pass values to PreparedStatement - last fifth argument is skipped - java

I have the following problem. I have the method which use the query to check if there is any reservation for given place in time from Start to End to check if the user can book this place in given time then returns Ture of False. My problem is that every time my ResultSet is equal to null. I do debug step by step and all variables are properly passed. With the debugger, I found that after passing 4 arguments (2nd-time start date) the fifth is skipped and myRs value remains null. Also, the 4th argument after passing is underlined with the green line but no communication is displayed. I am using Netbeans. I have no idea whats going on. Here goes my DBUtil method code:
public boolean doesBookExist(int number, Date start, Date end) throws Exception {
boolean result = false;
Connection myConn = null;
PreparedStatement myStmt = null;
ResultSet myRs = null;
try {
// get a connection
myConn = dataSource.getConnection();
// create sql for validation
String sqlValidate = "SELECT * FROM `rezerwacje_miejsc`"
+ " WHERE `NR_MIEJSCA`=?"
+ " AND (`START` BETWEEN ? AND ?"
+ " OR KONIEC` BETWEEN ? AND ?)";
myStmt = myConn.prepareStatement(sqlValidate);
myStmt.setInt(1, number);
myStmt.setDate(2, new java.sql.Date(start.getTime()));
myStmt.setDate(3, new java.sql.Date(end.getTime()));
myStmt.setDate(4, new java.sql.Date(start.getTime()));
myStmt.setDate(5, new java.sql.Date(end.getTime()));
// execute query
myRs = myStmt.executeQuery(sqlValidate);
// check if there was a match
result = myRs.next();
return result;
} finally {
// close JDBC objects
close(myConn, myStmt, myRs);
}

This is incorrect:
myRs = myStmt.executeQuery(sqlValidate);
It should be just:
myRs = myStmt.executeQuery();
The version of executeQuery accepting a string is a holdover from Statement (API design problem). You want the one without parameters, which is provided by PreparedStatement.
There's also a typo in the query that I assume must just be in the question, not the real code: You have mis-matched backticks (you have one after KONIEC but not before it).

Related

Result set always returns empty, should I not use executeQuery() on my prepared statement?

I've got users trying to register to a site. before they can register their username of choice is searched for in an SQL database to make sure it doesn't already exist.
the problem is the names are never searched because the ResultSet always returns empty. I think it's the prepared statement.
I think my prepared statement isn't executing. I'm using executeQuery() to execute my statement because that's how I've been inserting the usernames without any problem. I got the search ResultsSet part if (rs.next())... from the method that inserts the usernames. Same with the String SQL and the prepared statement stuff.
String SQL = "SELECT * FROM users WHERE username='" + getUsername() + "'";
System.out.println(SQL);
// prints out SELECT * FROM users WHERE username='whatever I searched'
// so this String is valid
if (db.getConn() != null){
System.out.println("connected to database");
// always prints
}
PreparedStatement preparedStatement = db.getConn().prepareStatement(SQL);
// preparedStatement.setString(1, getUsername());
ResultSet rs = preparedStatement.executeQuery();
// userNameCounter = rs.getString("username");
// putting this here returns an sqlexception. empty set
if (preparedStatement != null){
System.out.println("ps != null");
// prints this
}
if (rs != null){
System.out.println("rs != null");
// prints this
}
if (!rs.next()){
System.out.println("!rs.next");
// prints this
}
if (rs.next()) {
userNameCounter = rs.getString("username");
System.out.println("rs.next()");
// doesn't print
// so the resultset is empty
if (!userNameCounter.equals(getUsername())) {
System.out.println("that username is unique");
return true;
}
}
preparedStatement.close();
incorrectLabels.setText("That username is already taken");
incorrectLabels.setVisible(true);
System.out.println("that username is already there");
// this always prints. it shouldn't
return false;
So executeUpdate() requires an int but I'm not sure what I would put there. And doing just execute() throws an error Requires ResultSet found boolean. I don't think there are any syntax errors since the table is called users. Everything I try just leads me back to an error resulting from an empty set. let me know if you need more code but this is where the error is happening.
Thanks!
You are issuing a query to the database when using the SELECT statement therefore you use the executeQuery() method.
What looks confusing is the userNameCounter variable you're using. Where is it declared and what is it declared as? It looks like it may be a Integer variable which would bring me to ask....what do you think the rs.getString("username") method returns?
As a matter of fact...what's with all the rs.next() conditions for all those if statements?
The whole thing is rather confusing. If you want to see if a User Name already exists within a database table then you might do it something like this:
if (db.getConn() == null){
throw new RuntimeException("Method Error! You Are NOT Connected To Database!");
}
String suppliedUserName = getUsername();
String dbUserName = "";
String SQL = "SELECT username FROM users WHERE username=?";
PreparedStatement preparedStatement = db.getConn().prepareStatement(SQL);
preparedStatement.setString(1, suppliedUserName);
ResultSet rs = preparedStatement.executeQuery();
while (rs.next()) {
dbUserName = rs.getString("username");
}
rs.close()
preparedStatement.close()
/* Below we use the equalsIgnoreCase() method. You
don't want a supplied User Name to be that close
or that similar to another User Name already in
Database. If you do then just use equals() method. */
if (dbUserName.equalsIgnoreCase(suppliedUserName)) {
System.out.println("The User name (" + suppliedUserName +
") is already in use. Try another User Name.");
return false;
}
else {
System.out.println("The User name (" + suppliedUserName + ") is Unique.");
return true;
}
Of course this code isn't tested and I assume you have your try/catch in place to handle any SQLException. I merely provide this code to give you an idea of how it can be accomplished.

Value of ResultSet when the SQL statement is a wrong syntax?

I am using mySQL. As you see, the SQL statement is wrong at SELECT. So, I wonder what value the rs is?
I hope to get some advice. I thank you so much;
String sql = "SELCT * FROM user WHERE username = '" + username + "' and password = '" + password + "'";
ResultSet rs = stm.executeQuery(sql);
There would be no value because Statement.executeQuery(String) would throw a SQLException. As the linked Javadoc says,
Returns:
a ResultSet object that contains the data produced by the given query; never null
Throws:
SQLException - if a database access error occurs, this method is called on a closed Statement, the given SQL statement produces anything other than a single ResultSet object, the method is called on a PreparedStatement or CallableStatement
It will return you an exception having message like syntax error.
Easiest way to find is to debug your code by putting break points in code & examining / watching values of variables . Most IDEs have these debugging features. In addition to Elliott Frisch's answer, if I restructure your code like below then in case of invalid / incorrect SQL, control comes to catch block and you can see that value of rs remains null.
public void executeQuery(Connection conn, String username,String password) {
String sql = "SELCT * FROM user WHERE username = '" + username + "' and password = '" + password + "'";
ResultSet rs = null;
Statement stm = null;
try {
stm = conn.createStatement();
rs= stm.executeQuery(sql);
while(rs.next()) {
//Extract ResultSet here as per needed logic
}
} catch (SQLException e) {
// Your control comes here if query is wrong , put a break point at below line & examine value of rs
e.printStackTrace();
}finally {
// Close resources not needed after this method call like - result sets , statements & connection
}
}
Firstly statement won't execute, so next execution is depends on how you are going to handle that exception. So, if exception comes and if you handle also there will be null in ResultSet because no value assigned to it.

Why do I get java.sql.SQLException: ResultSet not open. Operation 'next' not permitted. java derby database?

I'm getting this error:
java.sql.SQLException: ResultSet not open. Operation 'next' not
permitted. Verify that autocommit is off.
when I'm trying to create instances from a db.
Current code:
try
{
connection.setAutoCommit(false);
stmt = connection.createStatement();
results = stmt.executeQuery("SELECT * from animalTable");
int AnimalCat = -1;
System.out.print(connection.getAutoCommit());
//getting error on line below
while(results.next())
{
int ID = results.getInt(1);
int Age = results.getInt(2);
String Name = results.getString(3);
String AType = results.getString(4);
String Breed = results.getString(5);
AnimalCat = results.getInt(6);
int Adoption = results.getInt(7);
String Gender = results.getString(8);
String Description = results.getString(9);
if(Gender == "Male"){
gen = true;
}
animal = new Animal(Age, AType, gen, Breed, Description, Name);
animalList.add(animal);
if(AnimalCat != -1){
ResultSet resultCat = stmt.executeQuery("SELECT * from CategoryTable where ID = " + AnimalCat);
//without this line below i get a cursor error
resultCat.next();
System.out.println(resultCat.getInt(1) +"\n\n " + resultCat.getString(2));
String Category = resultCat.getString(2);
if(Category == "Lost"){
Date input = resultCat.getDate(3);
LocalDate date = input.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
ResultSet personData = stmt.executeQuery("SELECT * from PersonTable where ID = " + resultCat.getInt(4));
Person person = new Person(personData.getString(2), personData.getString(3), personData.getString(4), personData.getString(5));
Category lost = new Lost(date, resultCat.getString(5), person);
animal.setAnimalCat(lost);
personList.add(person);
}
}
}
results.close();
stmt.close();
}
catch (SQLException sqlExcept)
{
sqlExcept.printStackTrace();
}
I have tried turning off auto commit like it says in the exception and also adding a finally block and closing the statement. From what I can see online that fixed others issues but no luck with mine.
I know the resultCat.next(); is behind the error somehow but I get an "Invalid cursor state - no current row" without it
You have a Statement, obtain a ResultSet from the statement, then obtain another ResultSet. This automatically closes the first ResultSet:
By default, only one ResultSet object per Statement object can be open
at the same time. Therefore, if the reading of one ResultSet object is
interleaved with the reading of another, each must have been generated
by different Statement objects. All execution methods in the Statement
interface implicitly close a statment's current ResultSet object if an
open one exists.
So when you call next on the first ResultSet an exception is raised. The Javadoc also tells you what to change: Create a second statement and use that to obtain the second ResultSet.

PreparedStatement return getUpdateCount() = -1

When we use the executeUpdate () method can not insert instructions to return ResultSet, such as a SELECT. I happen to have an update which to start a trigger, and the trigger have a command "Select * from table".
I could solve the problem by assigning this command to a variable as an example: "Select * from table " soon resultSet would be no problem for the JDBC executeUpdate.
The problem is that the system can work with triggers other integrated systems that have no domain and I can not change, so the option was to use the run command (), which as shown in the code image can I check if the return is a ResultSet ( return true). In the statement while discarding ResultSets generated in the trigger and getMoreResults returns me the number of rows affected by the Update, in the case of the frame in blue, using the statement returns the value 3, which is correct.
The problem is to use the PreparedStatement (red frame), where getUpdateCount is returning -1, but should return 3, which is the number of rows affected in the UPDATE.
Problem occurs in SQL Server 2012 database or 2008, it was not simulated with Oracle
Follows the code example with the existing trigger on the table that I'm doing update
I wonder if anyone knows why the return is different for getMoreResults.
Code Java
Trigger
public class TestarConexao {
public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException, SQLException {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver").newInstance();
Connection conn = DriverManager.getConnection("jdbc:odbc:magnus;user=rh;password=rh;MARS_Connection=yes;", "rh", "rhk");
Statement stmt = conn.createStatement();
boolean is = stmt.execute("update Usu_teste set usu_codigo = 1 where usu_codigo = 1");
while (is) {
System.out.println("There is ResultSet: " + is);
is = stmt.getMoreResults();
}
System.out.println("UpdateCount with Statement: " + stmt.getUpdateCount());
PreparedStatement prepStmt = conn.prepareStatement("update Usu_teste set usu_codigo = 1 where usu_codigo = 1");
boolean isPrep = prepStmt.execute();
while (isPrep){
System.out.println("There is ResultSet: " + isPrep);
isPrep = prepStmt.getMoreResults();
}
System.out.println("UpdateCount with PreparedStatement: " +prepStmt.getUpdateCount());
}
}

Getting an Integer From MySQL Select Statement

I would like to get an integer saved in my MySql DB into an Integer in Java. I have a Table, that includes PlayerName and Level. I would like to get The Level (Integer) From a Specific Player. And then Add Integer "Value" to it. Then put it back in the DB. My Code up to now is:
public void addinputPData(String loc, int value, Player player, String playername){
//add input Player Data
try{
logm("Putting Kill Death Int Data into " +player.getName() + "'s Profile!");
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/WebCom", "root", "MyPW");
int ovalue = -1;
Statement stmt = (Statement) con.createStatement();
ResultSet rs = stmt.executeQuery("SELECT "+loc+" FROM PlayerData WHERE PlayerName='"+playername+"'");
if(rs.next()){
ovalue= rs.getInt(loc);
}
if(ovalue == -1){
logm("Error Occured");
}
int nvalue = value + ovalue;
String insert = "UPDATE PlayerData SET "+ loc + "='" + nvalue + "' WHERE PlayerName='" + playername + "'";
stmt.executeUpdate(insert);
con.close();
}catch(Exception e){
logm("Could Not Send Data To MYSQL DATABASE SERVER s: "+ e.getMessage());
}
}
I don't know why this won't work, Is there anything obvious that i am missing? Thank you in advance.
So first what you must understand is that when you won't use parametrized statements, there is big danger of SQL Injection. So your code is very dirty written.
So anyway, use PreparedStatement with parametrized SQL statements for much more better performace. Now rewrite your code like this:
final String SELECT_QUERY = "SELECT level FROM PlayerData WHERE PlayerName = ?";
final String UPDATE_QUERY = "UPDATE PlayerData SET level = ? WHERE PlayerName = ?";
public boolean dataMethod(String playerName) {
Connection con = null;
PreparedStatement ps = null;
PreparedStatement ps1 = null;
ResultSet rs = null;
int dataLevel = 0;
try {
// getConnection etc...
ps = con.prepareStatement(SELECT_QUERY);
ps.setString(1, playerName) // first param is order of ? param, starts with 1(not 0)
rs = ps.executeQuery();
while (rs.next()) {
dataLevel = rs.getInt();
}
if (dataLevel > 0) {
ps1 = con.prepareStatement(UPDATE_QUERY);
ps1.setInt(1, dataLevel);
ps1.setString(2, playerName);
ps1.executeUpdate();
}
return true;
}
catch (SQLExcetion ex) {
Logger.getLogger(YourClass.class.getName()).log(Level.SEVERE, null, ex);
return false;
}
finally {
if (con != null) {
con.close();
}
}
}
Step by step, first init your statement, sets parameters if you have then when you use select, you will retrieve data in ResultSet that is table of data generated with query. imlicitly cursor in ResultSet is position before first row so you have to use next() method to go on current row and with the help of getter method you add data from ResultSet to your variable. Then you check if it's correct, if do, init second statement and execute it. And that's all.
But you should consider when you use more that 1 operation, sets autoCommit on false and all operations will do in one Transaction, because implicitly in JDBC is one operation = one transaction. And second, you should consider to use SQL stored procedures for add any data, update data or delete. It's more safer yet and less code. So let database working when it able to do it and also it's faster of course.
At the last, really you should think about this approach and makes your code more safer, faster and cleaner. Not have look on simplicity but on efficiency, compability and security.
More about SQL Injection
And when you decided right to use stored procedure, you can use it like this:
CREATE OR REPLACE PROCEDURE SOME_NAME(VARCHAR v_name PlayerData.name%type)
AS
BEGIN
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
// body
COMMIT;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
END;
So now you have to create String for call procedure.
final String CALL_SOMENAME = "{call SOME_NAME(?)}";
Then intead of PreparedStatement you have to use CallableStatement that is interface used to execute SQL stored procedures.
cs.prepareCall(CALL_SOMENAME); // Creates a cs object for calling db stored procedures
cs.setString(1, playerName);
cs.execute();
I don't know why many people searching the easiest way to do something and don't look at performance and readability of code.
Regards
In the UPDATE statement, you're inserting the value for the "loc" column as a string (there are single quotes around the value). If the database column is an integer, then this could be causing a problem.
Tip: JDBC provides a class called PreparedStatement. This class allow you to build SQL queries safely. It makes sure that all user input is properly escaped in order to avoid security vulnerabilities.
PreparedStatement ps = con.prepareStatement("UPDATE PlayerData SET " + loc + " = ? WHERE PlayerName = ?");
ps.setInt(1, nvalue);
ps.setString(2, playername);
ps.execute();

Categories

Resources