Resultset not open - java

I get following error on Result set
java.sql.SQLException: ResultSet not open. Verify that autocommit is OFF.
at org.apache.derby.client.am.SQLExceptionFactory40.getSQLException(Unknown Source)
at org.apache.derby.client.am.SqlException.getSQLException(Unknown Source)
at org.apache.derby.client.am.ResultSet.next(Unknown Source)
public ResultSet insertDb(int Id,String firstName,String lastName,String title) throws SQLException{
try {
try {
Class.forName(driver);
con = DriverManager.getConnection(connectionURL);
} catch (SQLException ex) {
Logger.getLogger(Connect.class.getName()).log(Level.SEVERE, null, ex);
} catch (ClassNotFoundException ex) {
Logger.getLogger(Connect.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println(con.getAutoCommit());
statement = con.createStatement() ;
res = statement.executeQuery("SELECT * FROM CUSTOMER") ;
con.setAutoCommit(false);
System.out.println(con.getAutoCommit());
while(res.next()){
if(res.getString("ID").equalsIgnoreCase(Integer.toString(Id))){
UNIQUE = false;
error= "Duplicate Entry Found Please Enter New Data";
throw new SQLException("Duplicate info<br>ID " + Id );
}
}
// IF value to be added IS UNIQUE
if(UNIQUE){
String qry1= "insert into CUSTOMER(ID, FIRSTNAME,LASTNAME,TITLE) values(?,?,?,?)";
stm = con.prepareStatement(qry1);
String ID=Integer.toString(Id);
stm.setString(1, ID);
stm.setString(2, firstName);
stm.setString(3, lastName);
stm.setString(4, title);
stm.executeUpdate();
}
}
catch(Exception e){
String errorMessage = "Exception caught : ";
System.out.println(errorMessage + e.toString());
}finally{
if (con != null){
con.close();
}
}
return res;
}

Try moving the setAutoCommit() and getAutoCommit() to before you create and execute the statement. Changing it after you execute the statement may be invalidating the query.

The problem is that you have closed your query before reading your resultset. Closing the query, closes the resultset, hence why you get the "ResultSet not open" error. You should close the query right at the end, in a finally block:
i.e. con.setAutoCommit(false);
will close the query and along iwth it it closes the resultset also.

Not strictly related, but your code probably doesn't do what you expect. This kind of read-modify-write code doesn't work well when there are multiple concurrent invocations.
If you imagine two invocations running though the code, it becomes clear that sometimes, depending on the execution order, BOTH invocations could reach the insert statement.
In addition, selecting from a table without using a WHERE clause is not generally useful. In this case you select '*', then iterate over all the results to see if "ID" == Id. The database is much much better at that than java is. You should add a where clause. (Note that this still won't solve the above problem)
Its also generally a bad idea to 'select *' from any table. Just pick the columns that you need. This will 'fail fast' if the schema changes and the columns that you need are no longer available, and will allow the database optimiser to do the 'right thing' about its disk accesses.
Finally, if its just a numeric ID that you are looking to assign, its normal practice to use 'autonumber' for these, rather than get the program to pick them. Different databases call them different things, so you might also know them as IDENTITY, or have to use a sequence.

In case it helps anyone down the line, I had the same error with Derby 10.5.1.1 that turned out to be a bug in the driver itself that would appear some times and not others depending on the underlying data. Upgrading the driver to a newer version (10.8.2.2) resolved the problem.

Related

MySql Connector SQL Statement does not return any values under java

I am using mySQL Connector in java and I need to write this long query where I join tables and return stocks of particular user. User_ID would be supplied by the java program hence i got ? and passed into the database. However I assume due to syntax error in java it does not return any values to program and simply fails. Query works perfectly in database.
String a = jTextField_User_Name.getText();
PreparedStatement ps = null;
String queryretrive = "SELECT DISTINCT Stock_Name FROM stockname,users,stock,userstock WHERE 'users.ID' = ? AND users.ID = userstock.User_ID AND userstock.Stock_ID = stock.Stock_ID AND stock.Stock_ID = stockname.Stock_ID";
ResultSet rs;
try {
ps = MyConnector.getConnection().prepareStatement(queryretrive);
ps.setString(1,a);
rs = ps.executeQuery();
if(rs.next())
{
System.out.println(rs.getString("Stock_Name"));
}else{
JOptionPane.showMessageDialog(null, "Error");
}
} catch (SQLException ex) {
Logger.getLogger(LoginForm.class.getName()).log(Level.SEVERE, null, ex);
}
Thanks.
WHERE 'users.ID' = ? AND users.ID =
Obviously, the second reference to users.ID doesn't need to be quoted, so why did you attempt to quote the first one?
Anyway, in MySQL " and ' are used to quote string literals and ` (backtick) is used to quote identifiers. If ANSI_QUOTES SQL mode is enabled, then " is used to quote identifiers, like other DBMS dialects do.
If you do need to quote, you need to quote each part separately, so the correct quoting would be `users`.`ID` or "users"."ID".
The fact that ' sometimes work for quoting identifiers is just weird lenient behavior and shouldn't be used, since it easily confused with string literals. Don't even know how MySQL decides whether it's a string literal or an identifier, so it's best to never do it.
this query is not long but this is hard to understand without your data model and code example.
if this is working in MySQLWorkBench should works from java. If this is not working from java you have poor error handling, or you haven't set properly parameter.
'users.ID' may be just users.ID
remove try/catch for testing purpose or handle this catch.
BTW.
With java/mysql ALWAYS handle finally to free connection, something like :
finally
{
try {if (rs != null) rs.close();} catch(Exception e) {}
try {if (statement != null) statement.close();} catch(Exception e) {}
}

Code executing time is incredibly long

I'm trying to move data from one table to another(both table are same basically), the method that I'm using is INSERT-SELECT.
The problem that I'm facing is my java program seem like frozen there, but I can still force close it with ^C easily, so I think it might be still alive but stuck for some reason.
This is my code which stuck in this problem
public String moveData(String sql, int day) {
Connection con = null;
PreparedStatement stmt = null;
int count;
try {
con = DriverManager.getConnection(DSN, Username, Password);
stmt = con.prepareStatement(sql);
stmt.setInt(1, day);
count = stmt.executeUpdate();
return String.valueOf(count);
} catch (SQLException e) {
System.out.println("SQL exception: " + e.getMessage());
e.printStackTrace();
return "false";
} finally {
try {
stmt.close();
} catch (Exception e) {
}
try {
con.close();
} catch (Exception e) {
}
}
}
and the SQL, executing it in SQL developer is really fast with 0.231 sec for 23k row of data
insert into Request_History (customer_id, request_id, status, transaction_date, last_modified)
SELECT customer_id, request_id, status, transaction_date, current_timestamp
from Request_Log
where transaction_date <= (sysdate - NUMTODSINTERVAL(:1 ,'DAY'))
I see no problem on them, is there anything that I missed?
Update
Since there's no resolve on the program and SQL command, I'd like to change a way of thinking on the DB side.
Could anyone please tell me what kind of privileges do I need to execute my INSERT-SELECT SQL command on 11g without problem? because from what I can see that this command would only needs basic privileges such as SELECT/INSERT/UPDATE/DELETE to execute.
The time of the whole insert process depends on three factors:
How many rows are in the query result set
Is there any index, which can be used at query level (best for this would be an index on Request_Log.transaction_date
Are there any constraints, indexes which have to be maintained during the insert phase (Request_History table)
Check the exec plan of the statement, to see if there's anything - worst things are full table scans. If you allowed, you can paste here the execution plan as well.
there is probably something wrong with the way you open your connection, something with you session parameters. You might not have enough undo space or another limiting factor. Maybe you can get a dba to check on it while you execute this over java vs. SQL Developer.
alter you statement to
create table Request_History_test
as SELECT
customer_id, request_id, status, transaction_date, current_timestamp
from
Request_Log
where
transaction_date <= (sysdate - NUMTODSINTERVAL(:1 ,'DAY'))
if this goes fast in contrast to your "insert select", then contact your DBA. There might be known issues with your undo space / redo logs. I'm not a DBA, so this answer is vague, I just had similar problems once.
oh, and check your dba_hist_sqlstat to see where the time is lost.

JDBC exception handling: warning suppression

I am currently learning some basic java SQL coding, making a basic terminal UI for my SQL project. I have been using PostgreSQL
I am using PreparedStatement to ensure myself from SQL injections, better be safe than sorry. PreparedStatement seems to always fire warnings for some reason, which I figured is a subclass to exceptions (and should get caught in the exceptions).
In my SQL triggers and functions I have created and tested the cases where I should fire exceptions, and they are all getting and working properly catch block.
I guess using #Supresswarnings to let the compiler know I want to do suppress my warnings, but I might want to catch some warnings in the catch block, so I might be looking for a different solution.
The problem / question is:
I would like to have my prints in the try block, that is no exceptions were fired.
What could be done to have my prints after the execution of preparedStmt.executeQuery in the try block?
Is using #SuppressWarnings usually considered good coding practice when dealing with exception handling like this?
If I am incorrect about preparedStatement.executeQuery() always fires warnings, what is considered warnings in SQL language?
My code:
void registerStudent(Connection conn, String toBeInserted, String insertedTo)
throws SQLException{
ResultSet res;
String query = "INSERT INTO Registrations VALUES (?, ?)";
PreparedStatement ps = conn.prepareStatement(query);
ps.setString(1, toBeInserted);
ps.setString(2, insertedTo);
try {
ps.executeQuery();
}catch (SQLException e) {
SQLWarning warning = ps.getWarnings();
if (warning != null){
System.out.println("Yay, insert succeeded!
values: "+ toBeInserted +" were inserted into
"+insertedTo);
}else {
System.out.println("Nothing inserted, here goes the big exception SQL fired for ya'll: "
+ e.getMessage());
}
}
}
There are still some flaws. I added also the case of an AUTOINCREMENT primary key - which you can retrieve after inserting.
Flaws:
List which fields you insert, such that a later addition of a column in the database does not cause problems, and the order of columns is clear in the code.
Use try-with-resources to close statement, result set and such, even when one returns inside, or an exception is thrown.
Use executeUpdate for INSERT (and similar modifying operations) returning an update count.
You catched the SQLException, which then should be rethrown, to let the caller determine what to do on gross failure.
SQLWarnings (as does the actual SQL and the SQLException) might be interesting,
though I not often see SQLWarnings being treated. Maybe forget it for such simple case, and instead try new SQL statements first in a separate SQL tool.
So:
/**
* #return the generated primary key, the Student ID.
*/
int registerStudent(Connection conn, String toBeInserted, String insertedTo)
throws SQLException {
String query = "INSERT INTO Registrations(ToBeInserted, InsertedInto) VALUES(?, ?)";
try (PreparedStatement ps = conn.prepareStatement(query),
Statement.RETURN_GENERATED_KEYS) {
ps.setString(1, toBeInserted);
ps.setString(2, insertedTo);
int updateCount = ps.executeUpdate();
if (updateCount == 1) {
try (ResultSet rs = ps.getGeneratedKeys()) {
if (rs.next()) {
int id = rs.getInt(1);
return id;
}
}
throw new SQLException("No primary key generated");
} else {
SQLWarning warning = ps.getWarnings();
Logger.getLogger(Xyz.class.getName()).info("Not added, values: "
+ toBeInserted + " were not inserted into "+ insertedTo + ": " + warning);
throw new SQLException("Not added");
}
}
}
Thank you very much I know I really shouldn't respond to your post but it helped be a lot. I think I got confused about ps.executeQuery() and ps.executeUpdate() methods.
executeQuery() generated a warning because there was nothing being returned, although it did work to execute the update to the database with that method.
The other tips and tricks is something I will bear with me as well.

problems with update statement in SQLite

I have created a database using SQLite. I want to update the value of a "features" column( type Blob)...but i do not know how to write the "update" statement .
This is what i tried:
try {
stat = conn.createStatement();
} catch (SQLException e) {
}
try {
byte[] b = getFunction();
stat.executeUpdate("update table set features="+b);
} catch (SQLException e) {
}
i get the follwing error :
java.sql.SQLException: unrecognized token: "[B#13a317a"
so i guess that "b" is the problem ?
[B#13a317a looks like a array to string result (b.toString() in this case). You should use a prepared statement for the blob like:
update table set features=?
An example is here.
Generally, you should never create a SQL by concatenating strings. This is the recipe for SQL injection problems.
Try this one with PreparedStatement:
Connection con = null;
PreparedStatement stmt = null;
try {
byte[] b = getFunction();
con = ...;
stmt = con.prepareStatement("update table set features=?");
stmt.setBytes(1, b);
stmt.executeUpdate();
con.commit();
}
catch (SQLException e) {
//handle exception (consider con.rollback()) and con maybe null here)
}
finally {
//close stmt and at least con here (all maybe null here)
}
Personally I am always using PreparedStatements. When you have to write a lot of this code then consider writing some Utility-Classes to reduce Boilerplate-Code.
In particular you should consider writing Utilty-Classes for null-safe calling methods on Connection, Statement and ResultSet methods when you are dealing with plain JDBC.
EDIT
What Thomas Jung wrote about preventing SQL Injections is another big pro for always using PreparedStatements. +1 for him :-)
stat.executeUpdate("update table set features="+b[0].toString());
you have to use +

Strange problem with JDBC, select returns null

I am trying to use JDBC and my query is working in some cases but not working in others.
I would really appreciate any help.
Some of my code:
public Result getSpecificTopic()
{
String query = "Select msg_body, msg_author from lawers_topic_msg";// where msg_id=2 order by msg_id desc";
try
{
con = mysql.getConnection();
//Statement stmt = con.createStatement();
PreparedStatement stmt = con.prepareStatement(query);
//stmt.setInt(1, topicId);
ResultSet rs = stmt.executeQuery(query);
int rowCount = rs.getRow();
specificTopic = ResultSupport.toResult(rs);
con.close();
stmt.close();
}
catch(Exception e)
{
}
return this.specificTopic;
}
public void setTopicId(String num)
{
this.topicId = Integer.parseInt(num);
}
public int getTopicId()
{
return this.topicId;
}
However if i change
String query = "Select msg_body, msg_author from lawers_topic_msg";
to the
String query = "Select msg_body, msg_author from lawers_topic_msg where msg_id = " + topicId;
Then the resultset retunrs nothing....
I am breaking my head here and still cannot figure out what is the problem
You still aren't closing your resources properly. That should be done in a finally block:
http://www.java-blog.com/correct-closing-jdbc-resources
As a first step, it'd be worth making sure an exception's not being thrown - at the very least log something in your catch() block.
Also be worth logging the SQL generated, and making sure that actually returns what you expect from the database when running it directly.
If you have multiple databases, it'd be worth confirming you're running against the one you think you are - I'm embarrassed to admit I've been caught out that way before.
several issues with your code, i'll keep it short:
don't encapuslate with try / catch at this layer, aspecially not since you're doing no error management. this.specificTopic looks global, so if your query fails it will return whatever was stored in this.specificTopic.
also try what BobbyShaftoe said. print in console or use your debugger. This should give you a good indication on what is wrong.
my first guess would be Integer.parseInt(num) could throw an exception. if so, the sql statement will be broken.
secondly, as Makach pointed out, there are several issues. first the catch-all
you should not use string concatenation, like
....where msg_id = " + topicId;
but rather
....where msg_id = ?"
stmt.set Int(1,topicId)
edit: it seems thats what you were trying anyways, SO sucks in some characters.

Categories

Resources