I want to re-execute the query whenever SQLException occurs and sometime I get the Exception of
SQLException occurred... com.mysql.jdbc.exceptions.jdbc4.
MySQLTransactionRollbackExceptionDeadlock
found when trying to get lock; try restarting transaction
My code is below. The database is MySQL InnoDB .. Please suggest...
String sqlquery = "UPDATE tbl_users SET abill=?"
+ " WHERE uid=? AND sms='2'";
PreparedStatement preStatement=null;
try{
con.setAutoCommit(false);
preStatement=con.prepareStatement(sqlquery);
preStatement.setString(1,billpush);
preStatement.setString(2,uid);
preStatement.executeUpdate();
con.commit();
}
catch(SQLException sE)
{
log.error("SQLException occurred... "+sE);
con.rollback();
}
finally {
if (preStatement != null) {
preStatement.close();
}
}
UPDATE tbl_users SET abill=billpush, asms ='2' WHERE uid='uid' AND sms='2' and asms<>'2'
This will prevent the dead lock just add a condition at the end as asms<>'2'. hope this solves the problem.
Simply set a flag to true after your dangerous operation:
bool ok = false;
while (!ok) {
ok = false;
try {
doSomethingFishy();
ok = true;
}
catch(Exception e) {
dealWithError(); // perhaps wait for a short while and increment a "retry" counter
}
}
Related
Im doing a Oracle Select for Update with java and it works on times and sometimes it hangs with the session and cannot remove the locked session (have to manually kill the session )
this works fine for most of the scenarios but when I deployed it in two servers ( web service ) and request them both at once this happens , I can't understand whether it's a problem with my code ,
my code
public boolean checkJobStatus(long taskId)
{
Connection con = null;
PreparedStatement selectForUpdate = null;
String lastJobStatus = null;
boolean runNow = false;
try
{
con = conPool.getConnection();
con.setAutoCommit(false);
selectForUpdate = con.prepareStatement("SELECT LAST_JOB_STATUS FROM ADM_JOB WHERE TASK_ID = ? FOR UPDATE ");
selectForUpdate.setLong(1, taskId);
ResultSet resultSet = selectForUpdate.executeQuery();
while(resultSet.next())
{
if (resultSet.getObject("LAST_JOB_STATUS") == null)
{
lastJobStatus = ScheduledJob.STATUS_FAILED;
}
else
{
lastJobStatus = resultSet.getString("LAST_JOB_STATUS");
}
}
if(ScheduledJob.STATUS_RUNNING.equalsIgnoreCase(lastJobStatus) || ScheduledJob.STATUS_STARTED.equalsIgnoreCase(lastJobStatus))
{
runNow = false;
// commit n update setting autocommit to true
selectForUpdate = con.prepareStatement("UPDATE ADM_JOB SET LAST_JOB_STATUS =? WHERE TASK_ID = ?");
selectForUpdate.setString(1, lastJobStatus);
selectForUpdate.setLong(2, taskId);
selectForUpdate.executeUpdate();
}
else
{
runNow =true;
// commit n update setting autocommit to true
selectForUpdate = con.prepareStatement("UPDATE ADM_JOB SET LAST_JOB_STATUS =? WHERE TASK_ID = ?");
selectForUpdate.setString(1, ScheduledJob.STATUS_STARTED);
selectForUpdate.setLong(2, taskId);
selectForUpdate.executeUpdate();
con.commit();
con.setAutoCommit(true);
}
} catch (SQLException e)
{
Logger.getLogger( "" ).log(Level.SEVERE, "Error in getting database connection", e);
try
{
con.rollback(); // rolling back the row lock in case of a exception
} catch (SQLException e1)
{
e1.printStackTrace();
}
}
finally
{
DBUtility.close( selectForUpdate );
DBUtility.close( con );
}
return runNow;
}
Commit occurs only in the else branch. If this condition doesn't happen, transaction is not closed, so a second thread hangs up forever on the select for update.
I am attempting at writing my own server as a personal project, however I'm running into some issues. I've finally completed the setup for a packet system between the Java server and the C# client which makes me very happy, even though I've had some help. Anyway, here's the code that I've written trying to get this to work properly. I created the SQLManager using static variables, because I read that the database connection should be static, if this is incorrect, please let me know.
Here's the error:
Exception in thread "main" java.lang.NullPointerException
com.fmeg.server.util.SQLManager.runQuery(SQLManager.java:37)
Here's my SQL Class:
public static boolean connectToDatabase() {
try {
connection = DriverManager.getConnection(host, credentials[0], credentials[1]);
connected = true;
} catch (Exception e) { connected = false; }
Misc.log("Database: " + database + " || Connection State: " + connected);
return connected;
}
public static boolean runQuery(String query) {
try {
ResultSet rs = checkQuery(query);
if(rs == null)
Misc.error("Result Set returned null.");
if(rs.next())
Misc.log("Current Row: " + rs.getRow());
return true;
} catch (SQLException e) {
e.printStackTrace();
return false;
}
}
public static ResultSet checkQuery(String query) throws SQLException {
try {
Misc.log(query);
return statement.executeQuery(query);
} catch (Exception e) {
destroyConnection();
return null;
}
}
private static void destroyConnection() {
try {
statement.close();
connection.close();
connected = false;
Misc.error("Database connection destroyed!");
} catch (Exception e ) { }
}
Apparently, the ResultSet is returning null, here's the output in the console.
[LOG]: Database: Unity3D || Connection State: true
[LOG]: Server <Test Realm> Successfully Started on port: 9955!
[LOG]: select * from `accounts`
[ERROR]: Result Set returned null.
Here's where I'm calling the query:
SQLManager.runQuery("select * from \'accounts\'");
Any pointers would be greatly appreciated, as I don't exactly see what the problem is. To answer these questions if the do arise, yes I do have a table called accounts, and yes it does have entries.
You have a syntax error on table name. Table names should not be a literal but should be quoted with back ticks. These back ticks are optional unless table name has any special chars in it or if it is a reserved word.
Just because of this error, the statement
return statement.executeQuery(query);
is causing an Exception and the method was returning a null for ResultSet.
You better catch the exception and see what the stacktrace says on it.
Change:
QLManager.runQuery("select * from \'accounts\'");
To:
QLManager.runQuery("select * from `accounts`");
You problem in this code:
if(rs == null) {
Misc.error("Result Set returned null.");
if(rs.next())
Misc.log("Current Row: " + rs.getRow());
In case any exception occurred in checkQuery method, it will return a null for ResultSet, then the code will proceed to rs.next(), which rs null, then a NullPointerException will raise.
What all you have to do is:
if(rs == null) {
Misc.error("Result Set returned null.");
return false;
}
if(rs.next()) {
Misc.log("Current Row: " + rs.getRow());
return true;
}
But you have to at least to log the error or throw the exception in checkQuery to figure out what is the exact problem that you are facing. not just return null object.
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));
I have the below code which is a simple jdbc java program which fetch the results upon execution of the query and retrieve the results and further store them in a resultset
The Statement.execute() method allows us to execute any kind of query like select, update. It returns boolean. If the return value is true, then it executed select query, get the ResultSet object and read the resulted records. If it returns false, then it can be update query, call getUpdateCount() method to get total records updated
public static void main(String a[]){
Connection con = null;
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
con = DriverManager.
getConnection("jdbc:oracle:thin:#<hostname>:<port num>:<DB name>"
,"user","password");
Statement stmt = con.createStatement();
//The query can be update query or can be select query
String query = "select * from emp";
boolean status = stmt.execute(query);
if(status){
//query is a select query.
ResultSet rs = stmt.getResultSet();
while(rs.next()){
System.out.println(rs.getString(1));
}
rs.close();
} else {
//query can be update or any query apart from select query
int count = stmt.getUpdateCount();
System.out.println("Total records updated: "+count);
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally{
try{
if(con != null) con.close();
} catch (Exception ex){}
}
}
Now my query is to I have to optimize this program in such a way like
1)It should print the time taken by query to execute at runtime
2) need to add the condition in such a way ...if the query takes more than 1 min then it should stop at that time means some counter should be there which will keep track of the time that it should not be more than 1 min
Please advise how to achieve
Log System.currentTimeMillis() (which returns the current time in milliseconds) as the last thing before executing your query. Subtract as soon as the execute() returns.
And, use Statement.setQueryTimeout(int seconds) to specify your timeout value as
stmt.setQueryTimeout(60);
long start = System.currentTimeMillis();
boolean status = stmt.execute(query);
System.out.println("Took " + (start - System.currentTimeMillis()) + " ms");
here is my very simple table (Postgres):
CREATE TABLE IF NOT EXISTS PERFORMANCE.TEST
(
test text NOT NULL UNIQUE
);
if I try to insert a String using the command below FROM the database,everything works as expected, not surprisingly a new row appears in the DB.
insert into performance.test (test) values ('abbbbaw');
However if I want to insert a String through JDBC, nothing gets inserted, although preparedStatement.executeUpdate() always returns 1.
Below is my method that should be working but it does not. Please tell me if I am missing something obvious.
I want to add that I never get any SQLException.
private void storePerformance() {
Connection conn= initializePerformanceConnection();
if (conn!= null) {
PreparedStatement insertPS = null;
try {
insertPS = conn.prepareStatement("insert into performance.test (test) values (?)");
insertPS.setString(1, queryVar);
int i = insertPS.executeUpdate();
LogManager.doLog(LOG, LOGLEVEL.INFO," numberofrows= "+i);
} catch (SQLException e) {
LogManager.doLog(LOG, LOGLEVEL.INFO,"Inserting query failed = "+queryVar,e);
}finally{
if(insertPS != null){
try {
insertPS.close();
} catch (SQLException e) {
LogManager.doLog(LOG, LOGLEVEL.INFO,"Closing PreparedStatement failed = "+queryVar,e);
}
}
try {
conn.close();
} catch (SQLException e) {
LogManager.doLog(LOG, LOGLEVEL.INFO,"Closing performanceConnection failed= "+ queryVar, e);
}
}
}
}
that was missing:
conn.commit();
(after the executeUpdate())
actually a new row was inserted but the DB rolled back immediately.
executeupdate is for a 'update table set column = value so on'. For insert just call execute of PreparedStatement.