While loop terminates only in one iterartion - java

try {
ResultSet rs = stat.executeQuery("select * from details where COURSEANDDEPT='"+username+"'");
//if (rs.next()) {
while (rs.next()) {
String logid=rs.getString(1);
char temp=' ';
ResultSet ag=stat.executeQuery("select type from login");
if (ag.next()) {
temp=ag.getString(1).charAt(0);
if (temp=='s' || temp=='S') {
String logid=ag.getString(1);
stat.executeQuery("insert into assignments values('"+logid+"','"+comments+"','P','"+userid+"','"+username+"')");
}
}
}
JOptionPane.showMessageDialog(this,"Assignment Sent To The Whole Class");
//} else {
//JOptionPane.showMessageDialog(this,"Invalid Branch");
//}
} catch (ClassNotFoundException | SQLException ex) {
Logger.getLogger(Assignments.class.getName()).log(Level.SEVERE, null, ex);
}
The while loop of rs.next() terminates only in one iteration even after containing 6 records in itself. How to rectify it?

The problem is that you use the same statement object for executing several queries. Addictional problems are
you don't close neither your statements neither your resultsets (see example).
you should use statements' parameters (see example).
you should not use select *, but list the columns you want back from statement (i'll not include this in the example).
one of the queries ("select type from login") is always repeated the same way, maybe there's an error on the query. Otherwise it should be executed once outside the main loop.
in the example i don't manage the connection but this should be done too
Lets suppose that you have a Connection object called conn
PreparedStatemet stat=null;
PreparedStatement innerStat=null;
PreparedStatement insertStat=null;
try {
stat=conn.prepareStatement("select * from details where COURSEANDDEPT=?");
stat.setString(1,username);
ResultSet rs = stat.executeQuery();
//if (rs.next()) {
while (rs.next()) {
String logid=rs.getString(1);
char temp=' ';
innerStat=conn.prepareStatement("select type from login");
ResultSet ag=innerStat.executeQuery();
if (ag.next()) {
temp=ag.getString(1).charAt(0);
if (temp=='s' || temp=='S') {
String logid=ag.getString(1);
ag.close();
innerStat.close();
insertStat=conn.prepareStatement("insert into assignments values(?,?,?,?,?)");
insertStat.setString(1,logId);
insertStat.setString(2,comments);
insertStat.setString(3,"P");
insertStat.setString(4,userid);
insertStat.setString(5,username);
insertStat.executeUpdate();
insertStat.close();
}//closes if on temp
} //closes if on ag
} //closes while
rs.close();
stat.close();
JOptionPane.showMessageDialog(this,"Assignment Sent To The Whole Class");
//} else {
//JOptionPane.showMessageDialog(this,"Invalid Branch");
//}
} catch (ClassNotFoundException | SQLException ex) {
Logger.getLogger(Assignments.class.getName()).log(Level.SEVERE, null, ex);
if(insertStat!=null) insertStat.close();
if(innerStat!=null) innertStat.close();
if(stat!=null) stat.close();
}

Your problem is that each connection can only handle one SQL statement at a time. You're trying to leave your first select statement open while you do a bunch of other statements. You can't do this on a single connection.
I suggest two changes to make this work.
Do the query against the login table first. Its result won't vary from one iteration to the next, so there is no point in repeating it over and over within the main loop.
Rewrite the queries against details and assignments as an insert/select statement. It's probably something like the following.
.
"insert into assignments " +
"select logid, ,'" + comments + "','P','" + userid + "','" + username + "' "
"from details " +
"where COURSEANDDEPT='"+username+"'"
Also, you might consider writing this with a PreparedStatement, depending on whether SQL injection attacks are a likelihood.

Related

Even though my RESULTSET is not empty I am not getting output. Using JAVA AND ORACLE DB

The database has the same format of date. Query is working fine in Oracle DB. In java the resultset is not empty. Cannot think of the possible reason for this problem. Please help.
try {
Class.forName(driverClass);
Connection cn=null;
cn=DriverManager.getConnection(url,username,password);
Scanner sc=new Scanner(System.in);
System.out.print("Enter Ship date in yyyy-mon-dd format: ");
String str=sc.next();
System.out.println(str);
//select PO_NUMBER from PURCHASE_ORDER where SHIPDATE=TO_DATE('2021-JAN-25','YYYY-MON-
DD');
String sql = "select PO_NUMBER from PURCHASE_ORDER where
SHIPDATE=TO_DATE('"+str+"','YYYY-MON-DD')";
System.out.println("Query exec");
Statement stmt = cn.createStatement();
ResultSet rs = stmt.executeQuery(sql);
if(rs.next())
System.out.println("Purchase Order Shipped on "+ str+" are: ");
else
System.out.println("empty rs");
while(rs.next()) {
System.out.println(rs.getInt(1));
}
cn.close();
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
}
OUTPUT : Enter Ship date in yyyy-mon-dd format: 2021-JAN-25
2021-JAN-25
Query exec
Purchase Order Shipped on 2021-JAN-25 are:
The answer by Elliott Frisch is spot-on. This answer provides you with some recommended practices.
Use PreparedStatement instead of Statement in case of a parametrized query in order to prevent SQL Injection.
Use try-with-resources so that the resources get closed automatically.
Using e.printStackTrace() is bad practices because the stack-trace is of no use to the end-user. The general rule is: If your method can not handle the exception (i.e. can not do something to recover from the exceptional state), it should not catch the exception and should declare throws with the method signature. This will ensure that the calling method will get an opportunity to handle the exception in the desired manner.
As per the documentation of ResultSet#next, it Moves the cursor forward one row from its current position. A ResultSet cursor is initially positioned before the first row; the first call to the method next makes the first row the current row; the second call makes the second row the current row, and so on.
It means that after making a call to ResultSet#next, you have to grab the value(s) from the ResultSet before making another call to ResultSet#next, which you have missed and therefore the values fetched by the ResultSet from the DB, on the first call to ResultSet#next, is getting wasted.
Either you handle it in the way, Elliott Frisch has suggested or you can do it in an alternative way shown in the following code.
Based on these recommendations, your code should be as follows:
Scanner sc = new Scanner(System.in);
System.out.print("Enter Ship date in yyyy-mon-dd format: ");
String str = sc.next();
String query = "select PO_NUMBER from PURCHASE_ORDER where SHIPDATE = TO_DATE(?, 'YYYY-MON-DD')";
try (Connection cn = DriverManager.getConnection(url,username,password);
PreparedStatement stmt = cn.prepareStatement(query)) {
stmt.setString(1, str);
ResultSet rs = stmt.executeQuery(query);
if(rs.next()) {
System.out.println("Purchase Order Shipped on "+ str+" are: ");
System.out.println(rs.getInt(1));
while(rs.next()) {
System.out.println(rs.getInt(1));
}
} else {
System.out.println("empty rs");
}
}
Your current while loop discards the first row (which is presumably the only row). Easiest solution I can see would be to change it to a do while in the if. Something like,
if(rs.next()) {
System.out.println("Purchase Order Shipped on " + str + " are: ");
do {
System.out.println(rs.getInt(1));
} while(rs.next());
} else {
System.out.println("empty rs");
}

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.

Java. Statement execution in cycle

I try to execute INSERT query in cycle:
String selectTableSQL = "SELECT * "
+ "FROM testTable";
ResultSet rs = stmt.executeQuery(selectTableSQL);
while (rs.next()) {
String rangeName = rs.getString("RANGENAME");
insertTableSQL = "INSERT INTO testTable2 "
+ "VALUES ('" + rangeName + "')";
try {
stmt.executeUpdate(insertTableSQL);
} catch (SQLException e) {
// do nothing
}
But after one iteration this cycle breaks. If I don't execute INSERT query and print rangeName to screen everything works perfectly (there are a lot of values, not only one). So the problem is in statement execution. How can I solve it?
Thank you very much!
Of course it does: you're using the same stmt
Create a new stmt2 variable and use it inside loop without destroying the previous one.
First: Never do so
} catch (SQLException e) {
// do nothing
}
Add a e.printStackTrace() to the catch block.
I think you get an exception when you do so. You may need a second statement variable.

Why rs.next() don't go to another record

If I remove beforeFirst() my function does only first record in ResultSet and go to end. If I use beforeFirst() I get an error ResultSet IS_TYPE_FORWARD_ONLY.
try {
ResultSet rs = stat.executeQuery("select _id, godziny_id from tblZmiany where harmonogram_id = " + h_id + " order by pracownik_id, Dzien");
rs.beforeFirst();
while (rs.next()) {
if (stat.executeUpdate("insert into tblWykonanie (Zmiana_id, Godziny_id) values ('" + rs.getLong(1) + "', " + rs.getInt(2) + ");") < 1) {
// Jeśli insert nie wstawił kolejnego rekordu
error_code = "Wystąpił problem podczas zatwierdzania harmonogramu.";
return false;
}
}
} catch (SQLException e) {
e.printStackTrace();
System.out.println(e.getMessage());
return false;
} catch (Exception e) {
error_code = e.getMessage();
return false;
}
return true;
You're using the same Statement object for both the SELECT and the INSERT. From the Javadoc:
A ResultSet object is automatically closed when the Statement object that generated it is closed, re-executed, or used to retrieve the next result from a sequence of multiple results.
To fix the problem, use a separate Statement object for the executeUpdate() call.
Also, I strongly advise you to change the code to use PreparedStatement with bound arguments (represented by ?). Building SQL statements bit by bit as you're doing right now could open up security vulnerabilities.
Your code has a major security flaw. You are vulnerable to SQL injection. Never, ever, ever, ever, ever, ever, ever, use string concatenation with SQL statements; use PreparedStatements instead!
harmonogram_id = " + h_id + " order by pracownik_id,
Take a look here to see how your application could be easily owned with simple tricks:
http://en.wikipedia.org/wiki/SQL_injection
To answer your question though, it depends on your database. You have to set a property during the connection creation:
Statement stmt = con.createStatement(
ResultSet.TYPE_SCROLL_SENSITIVE,
ResultSet.CONCUR_UPDATABLE),
ResultSet.HOLD_CURSORS_OVER_COMMIT);
From:
http://docs.oracle.com/javase/1.4.2/docs/guide/jdbc/getstart/resultset.html#1012735

SQLSTATE 24000 - Invalid Cursor State

I connect to a DB2 database and makes the following query. I don't understand why I get the error: "invalid cursor state".
public static void blivPar() {
try {
Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_UPDATABLE);
stmt.setMaxRows(1000);
ResultSet drenge = stmt.executeQuery("SELECT * FROM People WHERE sex='M'");
ResultSet piger = stmt.executeQuery("SELECT * FROM People WHERE sex='F'");
drenge.first();
piger.first();
int i=0;
while(drenge.next()) {
while(piger.next()) {
i++;
System.out.print(i);
stmt.execute("INSERT INTO Couples Values ('"+drenge.getString(1) +
"','" + drenge.getString(2) +
"','" + piger.getString(1) +
"','" + piger.getString(2) + "')");
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
Thank you.
Found this on the JDBC Javadocs for the Statement interface: "The object used for executing a static SQL statement and returning the results it produces.
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. "
see Statement javadoc
So it looks to me like you need two different Statements if you want two ResultSets open at the same time. Or you need to finish processing your first ResultSet and close it so you can re-use the Statement to create the second ResultSet.

Categories

Resources