Reusing PreparedStatement causes SQLException [duplicate] - java

This question already has an answer here:
java.sql.SQLException: Operation not allowed after ResultSet closed MySQL Java [duplicate]
(1 answer)
Closed 6 years ago.
Try with recources gives me following exception:
java.sql.SQLException: Operation not allowed after ResultSet closed
My code:
public Set<Tablet> viewAllTablets(int offset, int noOfRecords) throws OutOfRangeException {
Set<Tablet> tabletSet = new HashSet<>();
Tablet tablet = null;
try(Connection connection = dataSource.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("SELECT SQL_CALC_FOUND_ROWS * FROM tablets limit " + offset + ", " + noOfRecords + ";");
ResultSet resultSet = preparedStatement.executeQuery();
ResultSet resultSet1 = preparedStatement.executeQuery("SELECT FOUND_ROWS()");){
while (resultSet.next()){
tablet = new Tablet();
tablet.setTabletId(resultSet.getInt("idTablet"));
tablet.setName(resultSet.getString("name"));
tablet.setNeedRecepie(resultSet.getBoolean("need_recipe"));
tablet.setPrice(resultSet.getDouble("price"));
tablet.setTypeId(resultSet.getInt("type_id"));
tablet.setDescription(resultSet.getString("description"));
tablet.setTabletType(TypeFactory.getType(tablet.getTypeId()));
tablet.setWeight(resultSet.getDouble("weight_of_pack"));
tablet.setPillsCount(resultSet.getInt("pills_count"));
tabletSet.add(tablet);
}
if(resultSet1.next())
this.noOfRecords = resultSet1.getInt(1);
} catch (SQLException e) {
e.printStackTrace();
}
return tabletSet;
}

Executing a second query on the PreparedStatement implicitly closes the ResultSet from the previous query. From Statement:
By default, only one ResultSet object per Statement object can be open at the same time.
Use two different statements, something along these lines (note how resultSet1 is retrieved) although of course I don't know what the requirements of your FOUND_ROWS function are:
try (
Connection connection = dataSource.getConnection();
PreparedStatement preparedStatement = connection.prepareStatement("SELECT SQL_CALC_FOUND_ROWS * FROM tablets limit " + offset + ", " + noOfRecords + ";");
ResultSet resultSet = preparedStatement.executeQuery();
ResultSet resultSet1 = connection.createStatement().executeQuery("SELECT FOUND_ROWS()"); // ****
) {
while (resultSet.next()) {
tablet = new Tablet();
tablet.setTabletId(resultSet.getInt("idTablet"));
tablet.setName(resultSet.getString("name"));
tablet.setNeedRecepie(resultSet.getBoolean("need_recipe"));
tablet.setPrice(resultSet.getDouble("price"));
tablet.setTypeId(resultSet.getInt("type_id"));
tablet.setDescription(resultSet.getString("description"));
tablet.setTabletType(TypeFactory.getType(tablet.getTypeId()));
tablet.setWeight(resultSet.getDouble("weight_of_pack"));
tablet.setPillsCount(resultSet.getInt("pills_count"));
tabletSet.add(tablet);
}
if (resultSet1.next())
this.noOfRecords = resultSet1.getInt(1);
} catch (SQLException e) {
e.printStackTrace();
}
Also: Don't use Statement's executeQuery(String) on PreparedStatement. It really shouldn't be there, it's a flaw in the java.sql package design. In fact, the documentation for Statement#executeQuery says:
Note:This method cannot be called on a PreparedStatement or CallableStatement.

Related

Using Java and Mysql getting exception com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: [duplicate]

This question already has answers here:
MySQLSyntaxErrorException near "?" when trying to execute PreparedStatement
(2 answers)
Closed 6 years ago.
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 1 getting this exception
private String selectCustDetail= "SELECT NAME, PASSWORD, RESID, ACTIVATED, USERTYPE FROM USERDETAIL WHERE MOBILENO=?";
ResultSet rs;
//PreparedStatement preparedStatement = null;
PreparedStatement preparedStatement = null ;
try {
// preparedStatement = con.prepareStatement(selectCustDetail);
preparedStatement = con.prepareStatement(selectCustDetail);
preparedStatement.setString(1, mobileno.toString().trim());
rs = preparedStatement.executeQuery(selectCustDetail );
while (rs.next()) {
// LOGGER.info("fetching - 1" + mobileno);
System.out.println(rs.getString("name"));
userDetai.setName(rs.getString("name"));
userDetai.setPassword(rs.getString("password"));
userDetai.setRestaurant(rs.getString("resId"));
userDetai.setActivated(rs.getString("activated"));
userDetai.setType(rs.getString("userType"));
// LOGGER.info("fetching - 2" + userDetai.getActivated());
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
//LOGGER.info("Exception - " + e.getMessage());
dinepostcons.msg = dinepostcons.dbError;
return false;
}
finally
{try {
if (preparedStatement != null) {
preparedStatement.close();
}
Change
rs = preparedStatement.executeQuery(selectCustDetail );
to
rs = preparedStatement.executeQuery();
You want the method that invokes your preparedStatement with bind parameters. Not the method from Statement that takes a String without bind parameters.

What's wrong with my JDBC select prepared statement? [duplicate]

This question already has answers here:
right syntax to use near '?'
(3 answers)
Closed 7 years ago.
I'm trying to debug my prepared statement in java and I'm stuck on this checkEmail function that I implemented. When I go into debugging and it reaches the setString line, it shows NOT SPECIFIED in place of the '?'. If I hardcode 'findEmail' into the String query it will work and find the email. Here is the piece of code:
public static boolean checkEmail(String findEmail) {
Connection conn = EstablishConnection.conn;
boolean found = false;
try {
String query = "SELECT email FROM customers WHERE email=?";
Logging.debug(query);
PreparedStatement preparedStatement = conn.prepareStatement(query);
preparedStatement.setString(1,findEmail);
ResultSet rs = preparedStatement.executeQuery(query);
//Iterate through the results of the query
if (rs.next()) {
found = true;
}
preparedStatement.close();
} catch (Exception e) {
Logging.debug("Exception thrown in CustomerOperations.getCustomerInfo(): " + e.getMessage());
e.printStackTrace();
}
return found;
}
Try to replace this :
ResultSet rs = preparedStatement.executeQuery(query);
With:
ResultSet rs = preparedStatement.executeQuery();
Because you had already pass the query to prepareStatement : conn.prepareStatement(query);

How to get last inserted ID as Long in java mysql [duplicate]

This question already has answers here:
How to get the insert ID in JDBC?
(14 answers)
Closed 7 years ago.
I want to get the last inserted ID as long. Because the primary key of my table is of long data type.
Here's my code:
Connection connection = null;
Statement statement = null;
try {
String sql = "INSERT INTO testTable(name) VALUES('Anonym')";
connection = DriverManager.getConnection(DB_URL, USER, PASS);
statement = connection.createStatement();
long lastInsertedID = statement.executeUpdate(sql, Statement.RETURN_GENERATED_KEYS);
System.out.println("LAST INSERTED ID = "+lastInsertedID);
} catch (Exception e) {
e.printStackTrace();
}
I've tested that when the maximum value of integer reaches I get last 1 as last inserted_id.
By the way, I've gone through this post.
Thanks.
try with the following code snippet:
ResultSet rs= statement.getGeneratedKeys();
if (rs.next())
{
System.out.println("Last Inserted ID = "+rs.getLong(1));
}
Here's the full code:
Connection connection = null;
Statement statement = null;
try {
String sql = "INSERT INTO testTable(name) VALUES('Anonym')";
connection = DriverManager.getConnection(DB_URL, USER, PASS);
statement = connection.createStatement();
long lastInsertedID = statement.executeUpdate(sql, Statement.RETURN_GENERATED_KEYS);
ResultSet rs= statement.getGeneratedKeys();
if (rs.next())
{
System.out.println("Last Inserted ID = "+rs.getLong(1));
}
} catch (Exception e) {
e.printStackTrace();
}

maximum open cursors exceeded exception in java and oracle

I having problem with my code:
ERROR: ORA-01000: maximum open cursor exceeded. This code is called from multiple threads.
Q. is oracle cursors are differen than JDBC cursor(resultset)?
public static void viewTable(Connection con, String TBName)
throws SQLException {
Statement stmt = null;
String query = "select *from " + TBName;
try {
stmt = con.createStatement();
ResultSet rs = stmt.executeQuery(query);
while (rs.next()) {
String studentName = rs.getString("STD_NAME");
System.out.println(studentName + "\t");
}
} catch (SQLException e ) {
e.printStackTrace();
} finally {
if (stmt != null) { stmt.close(); }
}
}
Use try-with-resources to ensure that both statement and result set are closed.
String query = "select STD_NAME from " + TBName;
try (Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery(query)) {
while (rs.next()) {
String studentName = rs.getString("STD_NAME");
System.out.println(studentName + "\t");
}
} // Closes rs and stmt even with exceptions.
You should always close the ResultSet and the Statement. As you said, your code is accessed by many thread so a lot of Resultset will be open and never
closed.
Put the ResultSet variable out of the try catch block and close it in a finally, beside the Statement closing.

Java JDBC Incorrect Syntax Error

I have this method to load the objects, however when I am running the sql code it is giving me a Syntax error.
public void loadObjects() {
Statement s = setConnection();
// Add Administrators
try {
ResultSet r = s.executeQuery("SELECT * FROM Administrator;");
while (r.next()) {
Administrator getUser = new Administrator();
getUser.ID = r.getString(2);
ResultSet r2 = s.executeQuery("SELECT * FROM Userx WHERE ID= {" + getUser.ID + "};");
getUser.name = r2.getString(2);
getUser.surname = r2.getString(3);
getUser.PIN = r2.getLong(4);
JBDeveloping.users.administrators.add(getUser);
}
} catch (Exception e) {
System.out.println(e);
}
}
I have tried inserting the curly braces as stated in other questions, but I am either doing it wrong or it doesn't work.
This method should be able to load all administrators but I believe it is only inserting half of the ID.
The ID that it gets, consists of numbers and char; example "26315G"
the Error -
com.microsoft.sqlserver.jdbc.SQLServerException: Incorrect syntax near '26315'.
Edit -
private java.sql.Connection setConnection(){
java.sql.Connection con = null;
try {
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
String url = "jdbc:sqlserver://" + host + ";DatabaseName=" + database + ";integratedSecurity=true;";
con = DriverManager.getConnection(url, username, password);
} catch(Exception e) {
System.out.println(e);
}
return con;
}
public void loadObjects() {
java.sql.Connection con = setConnection();
// Add Administrators
try {
PreparedStatement sql = con.prepareStatement("SELECT * FROM Administrator");
ResultSet rs = sql.executeQuery();
while (rs.next()) {
Administrator getUser = new Administrator();
getUser.ID = rs.getString(2);
PreparedStatement sql2 = con.prepareStatement("SELECT * FROM Userx WHERE ID=?");
sql2.setString(1, getUser.ID);
ResultSet r2 = sql2.executeQuery();
getUser.name = r2.getString(2);
getUser.surname = r2.getString(3);
getUser.PIN = r2.getLong(4);
JBDeveloping.users.administrators.add(getUser);
}
} catch (Exception e) {
System.out.println(e);
}
}
Actually it is not the way to do that in JDBC. That way, even if you sort your syntax error, your code is prone to sql injection attacks.
The right way would be:
// Let's say your user id is an integer
PreparedStatement stmt = connection.prepareStatement("select * from userx where id=?");
stmt.setInt(1, getUser.ID);
ResultSet rs = stmt.executeQuery();
This way you are guarded against any attempt to inject SQL in your application request parameters
First of all: if you use concurrently result-sets, you must use separate statements for each one of them (you can not share Statement s between two r and r2). And more, you lack r2.next() before reading from it.
On the other hand: it would be much more effective to use PreparedStatement in the loop that to rewrite the query all the time.
So I'd go for something like this:
public void loadObjects() {
try (
Statement st = getConnection().createStatement();
//- As you read (later) only id, then why to use '*' in this query? It only takes up resources.
ResultSet rs = st.executeQuery("SELECT id FROM Administrator");
PreparedStatement ps = getConnection().prepareStatement("SELECT * FROM Userx WHERE ID = ?");
ResultSet r2 = null;
) {
while (rs.next()) {
Administrator user = new Administrator();
user.ID = rs.getString("id");
ps.setInt(1, user.ID);
r2 = ps.executeQuery();
if (r2.next()) {
user.name = r2.getString(2);
user.surname = r2.getString(3);
user.PIN = r2.getLong(4);
JBDeveloping.users.administrators.add(user);
}
else {
System.out.println("User with ID=" + user.ID + " was not found.");
}
}
}
catch (Exception x) {
x.printStacktrace();
}
}
Please note use of Java7 auto-close feature (you didn't close resources in you code). And last note: until you are not separating statements in your queries, as to JDBC documentation, you should not place ';' at the end of statements (in all cases you shouldn't place ';' as the last character in you query string).
You should not use {} and you should not append parameters into a SQL query like this.
Remove the curly braces and use PreparedStatement instead.
see http://www.unixwiz.net/techtips/sql-injection.html

Categories