Execute a SQL query in a loop - java

I have this scenario. I will trigger a job in the server and as soon as the job is triggered an entry will be made into the job table with Execution_status_code as 1. I need to wait for some time say 5 mins and recheck the Execution_status_code value. As soon as the value is changed to 2, I need to proceed further.
I am using an existing connection for connecting to the database. I need to execute the SQL and if the SQL output is In progress, I need to wait for some time and then again execute the statement. Do this until the SQL output is success, until then keep waiting.
Below is the code I have tried.
Thread t = new Thread();
java.sql.Connection conn_javaComp = (java.sql.Connection)globalMap.get("conn_tNetezzaConnection_1");
java.sql.Statement st = null;
java.sql.ResultSet rs = null;
String check = null;
String dbquery_javaComp = "select case when EXECUTION_STATUS_CODE = 2 then 'Success' when EXECUTION_STATUS_CODE = 1 then 'In progress' else 'Failure' end as EXECUTION_STATUS_CODE from JOB_BKUP_NCR where JOB_TYPE_CODE="+context.JobTypeCode+" and Load_id = (select max(load_id) from JOB_BKUP_NCR where job_type_code="+context.JobTypeCode+") and START_DATETIME = (select max(START_DATETIME) from JOB_BKUP_NCR where job_type_Code="+context.JobTypeCode+")";
try
{
do
{
st = conn_javaComp.createStatement();
rs = st.executeQuery(dbquery_javaComp);
if(rs.next())
{
check = rs.getString(1);
System.out.println(check);
if (check.equalsIgnoreCase("In Progress"))
{
t.sleep(1000);
System.out.println("thread executed1");
System.out.println(dbquery_javaComp);
System.out.println(check);
}
}
else {
System.out.println(" No data found");
}
}while (!"Success".equals(check));
}
catch (Exception e) {
e.printStackTrace();
} finally {
try {
if( rs != null)
rs.close();
if( st!= null)
st.close();
}
catch (Exception e1) {
e1.printStackTrace();
}
}
The output i am getting is 'In Progress'. The loop is struck at In progress even after i change the value in the database. I am not sure where i am doing wrong. Any suggestions?

You are creating a new statement and a new resultset inside the loop, and so, they should be close inside the loop. I am thinking that your connection got corrupted with multiple statements and resultset without closing them. Please try to close them and see if that work.

The data that you are seeing will be cached.
Try closing and re-opening your DB connection. This may not even be good enough if you are using DB pooling.

There are many things I can foresee going wrong with your code. For once most DBMS will either lock the rows until you commit / close the connection or give you a snapshot of the data instead, hence you don't see the updated value or the transaction that supposed to update it wouldn't go through. Try comitting or close/reopen the transaction per loop iteration.
I would also doubt if this is a good code design as you are doing "polling". Consider if you can find other method of getting notified of the event.

try
{
//declare here your statement and resultset
st = conn_javaComp.createStatement();
rs = st.executeQuery(dbquery_javaComp);
do
{
if(rs.next())
{
check = rs.getString(1);
System.out.println(check);
if (check.equalsIgnoreCase("In Progress"))
{
t.sleep(1000);
System.out.println("thread executed1");
System.out.println(dbquery_javaComp);
System.out.println(check);
}
}
else {
System.out.println(" No data found");
}
}while (!"Success".equals(check));

Related

MYSQL Insert query not updating data to the table in JAVA

I am working on a JAVA program which need to update database from text files. I have successfully inserted and updated data. But i am facing a problem with here, this method. Query runs without error and giving me the response. But the database table is not updating.
private void filteData() {
System.out.println("filteData");
Statement statementAtenLogInsert = null;
Statement statementqCheck = null;
Statement statementUpdateProLog = null;
Statement statementEnterError = null;
ResultSet rs = null;
int rcount;
//Update successfull attendance_test
String attenLogInsertSuccess = "INSERT INTO attendance_log (user_id, check_in, check_out) SELECT user_id, check_in, check_out FROM process_log WHERE flag = 'S'";
try {
statementAtenLogInsert = connection.createStatement();
statementAtenLogInsert.execute(attenLogInsertSuccess);
int qSuccess = statementAtenLogInsert.executeUpdate(attenLogInsertSuccess);
System.out.println("qSuccess " + qSuccess);
if(qSuccess > 0){
String deleteProcessLog = "DELETE FROM process_log WHERE flag = 'S'";
statementAtenLogInsert.execute(deleteProcessLog);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Here the attenLogInsertSuccess and deleteProcessLog queries are not working. Mean nothing happened from database table side. But qSuccess giving me a value. That means attenLogInsertSuccess is triggering. But nothing happened from mysql side.
You need to close your connection in order to flush the changes to the database.
Try adding connection.close(); somewhere in your pipeline, typically you close the connection in a finally block to ensure it is always closed but it appears you have defined your connection elsewhere, presumably for re-use in the calling function.
You also need to close your statements before closing the connection. See this similar answer for the pattern.

Can I put two Selects in a try?

try {
Connection lig = DriverManager.getConnection(
"jdbc:mysql://localhost/gym", "root", "0000");
PreparedStatement inst = lig
.prepareStatement("SELECT * FROM produtos_has_historico WHERE Produtos_idProdutos AND Historico_idHistorico");
ResultSet a = inst.executeQuery();
while (a.next()){
DefaultListModel model = new DefaultListModel();
model.addElement(a);
}
} catch( Exception e ){}
In this Select, I get the id historic and the id product, but I wanted to get also the name and price of the products that are in my other table "products" to add to my Jlist, can I use two selects ? Thank you.
It's not a problem to have two selects in a single try-catch block.
If you want to handle the generated exception the same way regardless of where it occurred, then I don't see a problem with enclosing multiple statements in the same try block.
Yes, it's fine to put multiple calls that may fail into a single try/catch block — in fact, that's a big part of why we have try/catch blocks (and exception handling in general), to move the code that handles exceptional things (failures) out of the way of the main code, so it's easier to understand the main code.
Compare these bits of pseudo-code
result = doThis();
if (result != success) {
handleTheFailure(result)
} else {
result = doThat();
if (result != success) {
handleThefailure(result);
} else {
result = doTheOther();
if (result != success) {
handleTheFailure(result);
}
}
}
vs.
try {
doThis();
doThat();
doTheOther();
}
catch (failure) {
handleFailure(failure);
}
More in the Java tutorial on exceptions.
No problem. I also recommend you use try-with-resources instead and be more specific about the exceptions you want to catch:
try (Connection conn = DriverManager.getConnection("...")) {
PreparedStatement ps1 = conn.prepareStatement("...");
try (ResultSet rs1 = ps1.executeQuery()) {
/* Parse first result */
}
PreparedStatement ps2 = conn.prepareStatement("...");
try (ResultSet rs2 = ps2.executeQuery()) {
/* Parse second result */
}
} catch (SQLException ex) {
for (Throwable t : ex) {
t.printStackTrace();
}
}
Instead of going for two selects - you can write a SQL query having a join in it .
You will be able to perform the join if you have common columns in your tables.
Then you can write a query using join and then the same code you can use to perform the operations and you can fetch all the values that you want.
For SQL joins basic - you can visit this site -
http://www.w3schools.com/sql/sql_join.asp

Java, code works, but exception is still thrown

I am creating a simple registration frame that adds records onto a database. It gives me an error message every time it runs the SQL query that adds records in the database, however it still adds them, but because of that my programs gets to a standstill, instead of opening another window.
here's that part of the code:
regButton.addActionListener(new ActionListener() {
#Override public void actionPerformed( ActionEvent e ) {
//Execute when button is pressed
if( uNameField.getText().equals("")
|| new String(newPassField.getPassword()).equals("")
|| new String(repeatPassField.getPassword()).equals("") ) {
errorLabel.setForeground(Color.red);
errorLabel.setText("Some fields are left blank");
}
else if( new String(newPassField.getPassword()).equals(
new String(repeatPassField.getPassword()))){
Statement stmt;
ResultSet res;
try
{
//SET USERNAME AND PASSWORD FROM FIELDS TO UPPER CASE
String username = uNameField.getText().toUpperCase();
String password = new String(newPassField.getPassword()).toUpperCase();
//SQL INSERT QUERY
String sql;
sql = "INSERT INTO Employees VALUES ('" +username +"','" +password +"');";
stmt = con.createStatement();
res = stmt.executeQuery(sql);
System.out.println("Added to database!");
con.close();
}
catch(SQLException exe) {
System.out.println("Error creating or running statement: " + e.toString());
try {
con.close();
}
catch(Exception eex){}
}
}
else {
errorLabel.setForeground(Color.red);
errorLabel.setText("Password missmatch");
}
}
Every time it registers a new employee (user) it displays this "Error creating or running statement: ..... " although, I can find the newly added employees in the employee list.
What may be causing this problem?
Before we get to your specific problem, some general advice:
Connection con = ...
try {
// your stuff
}
catch (Exception e) {
e.printStackTrace();
}
finally {
try {
con.close();
} catch (Exception e) {
e.printStackTrace();
}
}
The way you are doing it now not only swallows the exception, but also avoids printing its stacktrace. And close must be performend once and only once, regardless of the exception.
If you are on Java 7, this would be much easier:
try (Connetion con = ...) {
// stuff to do
}
catch (Exception e) {
e.printStackTrace();
}
The closing in a finally is now done automatically.
Specifically about your exception, you execute an INSERT by calling executeQuery. This method sends the statement to the DB, which properly executes it, but its response back to the JDBC is not a ResultSet. This is where it blows up, after the record is already inserted. Since you are in autocommit mode, there is no transaction to roll back. Lesson: always use transactions.
You need to use executeUpdate for SQL INSERTs
int rowCount = stmt.executeUpdate(sql);
I hate seeing code written this way. You didn't ask about this, and my comment won't solve your problem, but I think it needs to be said.
You're creating a maintenance nightmare for yourself by putting persistence code in a Swing Listener method.
A better idea is to think about objects in a way that gives them a single responsibility.
Take your persistence code and move it into a separate class that you can develop and test on its own. Once it's working, give a reference to the class that needs it.
Your code will be more modular, easier to test, more reusable, and less of a nightmare to understand.
Uncle Bob Martin has a succinct mneumonic for this and other ideas worth remembering: SOLID.
why dont you try PreparedStatement
try{
//SET USERNAME AND PASSWORD FROM FIELDS TO UPPER CASE
String username = uNameField.getText().toUpperCase();
String password = new String(newPassField.getPassword()).toUpperCase();
//SQL INSERT QUERY
PreparedStatement pstmt = con.prepareStatement("insert into Employees values(?,?)");
pstmt.setString(1,username);
pstmt.setString(2,password);
if(!pstmt.execute())
{
//means your code worked correctly
System.out.println("Inserted successfully");
}
else
{
System.out.println("Unsuccessfull");
}
}
catch(Exception ex)
{
ex.printStackTrace();
}

Java MySQL get last row

So I'm having issues with my program. Basically this far the program is like a MySQL based chat. It stores messages in database and reads them. I'm having problems with the reading. What it does right now is ever 5 seconds re-read all the messages in the database. I tried to make it read only the new messages but that's not working out too well. This is my code:
public static void readChat()
{
try
{
MySQL.sqlConnect();
try
{
Statement st = con.createStatement();
ResultSet res = st.executeQuery("SELECT * FROM table1");
while (res.next())
{
if (lastLine < res.getInt("id"))
{
String message = res.getString("message");
Gui.out.append(message + "\n");
lastLine = res.getInt("id");
}
}
}
catch (SQLException s)
{
System.out.println("SQL code does not execute.");
}
MySQL.sqlDisconnect();
}
catch (Exception e)
{
e.printStackTrace();
}
}
I'm not sure how to make this efficient. It takes way too long to execute that. If the id is 23 I can't even see the messages appear because it takes longer than 5 seconds. I added the
if (lastLine < res.getInt("id"))
and
lastLine = res.getInt("id");
in my effort to make it read only the new messages but it did not work as expected. I think it still executed line by line, just doesn't show it in the chat. There's got to be an easier way.
EDIT: Alright, so I fixed the problem with not seeing messages, (I forgot to remove the part of the code that cleared the chat every 5 seconds). But it still takes a long time to send messages, about 3-4 seconds?
Try this, and you will wonder :)
ResultSet res = st.executeQuery("SELECT * FROM table1 where id > "+lastLine);
instad
ResultSet res = st.executeQuery("SELECT * FROM table1");
and get result without if
while (res.next())
{
String message = res.getString("message");
Gui.out.append(message + "\n");
lastLine = res.getInt("id");
}
Of course make sure index on id field
you can just read the required rows, currently you are reading all the rows try following,
public static void readChat()
{
try
{
MySQL.sqlConnect();
try
{
Statement st = con.Preparestatment("SELECT * FROM table1 where id > ?");
st.setInt(0,lastLine);
ResultSet res = st.executeQuery();
while (res.next())
{
String message = res.getString("message");
Gui.out.append(message + "\n");
lastLine = res.getInt("id");
}
}
catch (SQLException s)
{
System.out.println("SQL code does not execute.");
}
MySQL.sqlDisconnect();
}
catch (Exception e)
{
e.printStackTrace();
}
}
You still iterate through all results. If you have some way of storing the time at which messages are sent i.e creating a time column, you can try to shorten how many results are returned by doing
ResultSet res = st.executeQuery("SELECT * FROM table1 WHERE id = ? AND time > ?");
where the first ? is the id of the user and the 2nd ? is the time of the last read message. This is based off the assumption id is some unique user id.
What about maintaining a list, add new message to that list when you save it to the database and just read the new messages from that list and clear it at the end of readChat()?

exhausted resultset error when i get the name of the columns

i'm trying to get the type and the name of the result and when enter in the loop, excuting somo instructions about the metadata the resulset.next changed from true to false, and give the error java.sql.SqlExcepcion exhausted resultset. Any ideas? i really dont know how solved it because i read the post with the solution of this problem and validate if the resultset it's null before begin the loop. I'm called this method with a scheduler of quartz. I'm using this in a j2ee aplication and the example it's this
try
{
InitialContext ctx = new InitialContext();
WrapperDataSource wrapperDataSource = (WrapperDataSource)ctx.lookup(systemLogger.getConfigurationParameters().getDataSource());
conn = wrapperDataSource.getConnection();
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver").newInstance();
conn = DriverManager.getConnection(url,login,password);
if (conn != null)
{
stmt = conn.createStatement();
res = stmt.executeQuery(query);
if (res != null)
{
while (res.next())
{
for (int i = 0; i < columnlength; i++)
{
String columnName = metadata.getColumnName(i+1);
if (metadata.getColumnName(i+1).equalsIgnoreCase(systemLogger.getColumnStatus()))
{
columnStatusType = metadata.getColumnType(i+1);
}
else if (metadata.getColumnName(i+1).equalsIgnoreCase(systemLogger.getColumnDocumentId()))
{
columnDocumentIdType = metadata.getColumnType(i+1);
}
else if (metadata.getColumnName(i+1).equalsIgnoreCase(systemLogger.getColumnTimer()))
{
columnTimerType = metadata.getColumnType(i+1);
}
}
}
}
else
{
__log.error("No results found for the query");
throw new PtmServiceException("No se encontraron resultados para el query");
}
}
else
{
__log.error("Could not create the connection");
throw new PtmServiceException("No se pudo crear la conexion");
}
}
catch(Exception e)
{
__log.error("Error in the execution of the query");
throw new PtmServiceException("Error ejecutando la busqueda");
}
finally
{
res.close();
stmt.close();
conn.close();
}
The variable columnlength seems to hold a value larger than the number of columns returned by the query. Try with a smaller columnlength.
finally, i see the problem, while i'm debugging the code with ecplise in the view of the expressions i added the follow expression res.next(), then each sentence that i pass for the step into bring the consequence that expression that evaluate if the resultset has more rows, be evaluated again. In some point the resultset has evaluated all the rows for each step into that i made in the process of debugging. The only thing that i have to do was eliminate the expression and works fine...
The problem might not be with the code but instead could be the database. Double check that the TABLE IS NOT EMPTY. You get this error if the table is empty. Keep in mind that databases like Oracle require a commit after all your insert, update, alter statements .Your changes might not be visible outside the database till you run a commit over the your db, I was having this problem for quite a long time. I kept on checking the table with select statement but the problem with my oracle db was that I had not issued a commit over my db.

Categories

Resources