Rollback is throwing an SQL error - java

Trying to do a rollback, when the rollback kicks in it throws an SQL Exception. What am I doing wrong??? I've checked the other posts but cant find anything to explain how to fix this. I've tried using savepoints and it says those are not able to be implemented. Do rollbacks always throw this error? Using MySQL Server and northwinds DB.
Stack Trace:
TESTING TRANSACTION FAILURE
Connecting to database at jdbc:mysql://localhost:3306/northwind ...
Connecting...
Checking for transaction support...
Beginning a transaction...
Looking up customer 'ACJO' ...
Connecting to database at jdbc:mysql://localhost:3306/northwind ...
Connecting...
select * from customers where CustomerID = ?
Found customer.
Adding a new order to the database...
> insert into orders(OrderDate) values(?)
> select OrderID from orders where OrderDate = ?
Updating an order...
> update orders set orders.BadField = ? where orders.OrderID = ?
**** Rolling back transaction ****
java.sql.SQLException: Unknown column 'orders.BadField' in 'field list'
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:1997)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1167)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1278)
at com.mysql.jdbc.Connection.execSQL(Connection.java:2247)
at com.mysql.jdbc.PreparedStatement.execute(PreparedStatement.java:1371)
at advanced.jdbc.northwind.TransactionDemo.updateOrderMistake(TransactionDemo.java:281)
at advanced.jdbc.northwind.TransactionDemo.testTransactionFailure(TransactionDemo.java:216)
at advanced.jdbc.northwind.TransactionDemo.main(TransactionDemo.java:425)
CODE:
public void testTransactionFailure() {
System.out.println("\n\nTESTING TRANSACTION FAILURE");
Connection connection = null;
try {
connection = getConnection();
System.out.println("Checking for transaction support...");
// TODO 04. Get the database metadata.
DatabaseMetaData databaseMetadata = connection.getMetaData();
// TODO 05. Determine if the database supports transactions.
boolean supported = false;
supported = databaseMetadata.supportsTransactions();
if (supported) {
System.out.println("Beginning a transaction...");
// TODO 06. Begin database transaction.
connection.setAutoCommit(false);
// create a new customer
String companyName = "ACME Products Ltd.";
String contactName = "John Doe";
String customerID = createCustomerID(contactName, companyName);
// check for customer before inserting
if (!customerExists(customerID)) {
addCustomer(customerID, companyName, contactName);
}
// add the order
int orderID = insertOrder(connection, customerID);
// oops, forgot shipping city so let's update it
updateOrderMistake(connection, orderID, "Timbuktu");
// TODO 07. Complete the transaction.
System.out.println("Committing");
connection.commit();
} else {
System.err.println("Transactions not supported!");
}
} catch (SQLException e) {
if (connection != null) {
System.out.println("**** Rolling back transaction ****");
// TODO 08. Roll back the transaction.
try {
connection.rollback();
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
e.printStackTrace();
} finally {
try {
if (connection != null) {
// TODO 09. Release resources.
connection.close();
connection = null;
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

Related

Get the Database name through JDBC with UCanAccess

EDIT:
I was testing out this code that I found in another post to look for the database name:
public static String getDBname(Connection conn) {
String result = null;
int i = 0;
try {
ResultSet rs = conn.getMetaData().getCatalogs();
while (rs.next()) {
System.out.println(rs.getString(i));
i ++;
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return result;
}
However it just returns me this error:
net.ucanaccess.jdbc.FeatureNotSupportedException: Feature not supported.
at net.ucanaccess.jdbc.UcanaccessDatabaseMetadata.getCatalogs(UcanaccessDatabaseMetadata.java:310)
Is there another way to do this?
For UCanAccess, the "database name" is just the name of the .accdb or .mdb file. That can be retrieved by extracting it from the connection URL as returned by
conn.getMetaData().getURL()
e.g.,
jdbc:ucanaccess://C:/Users/Public/UCanAccessTest.accdb;memory=false

My ResultSet is always closed when I return it from my method

I have the following class:
public class Refunds {
ResultSet dataToHash = null;
public Refunds (String UrnId) {
Database db = null;
CallableStatement callable;
String query = "select * from testmdb.dbo.ApEdiZcusSaSendFile where SourceID='LAN' and UrnID=?";
// Get database connection
try {
db = new Database("jdbc/refund");
} catch (NamingException | SQLException e1) {
e1.printStackTrace();
}
// Run the query
try {
callable = db.connection.prepareCall(query);
callable.setString(1, UrnId);
dataToHash = callable.executeQuery();
} catch (SQLException s) {
System.out.println("A SQL exception was thrown while running the query: ");
s.printStackTrace();
} catch (Exception e) {
System.out.println("A general exception was thrown while running the query: ");
e.printStackTrace();
} finally {
db.closeConnection();
}
}
public ResultSet getDataToHash() {
return dataToHash;
}
}
And I use it like this:
// Get the result set
Refunds refunds = new Refunds(urnId);
ResultSet dataToHash = refunds.getDataToHash();
However, every single time dataToHash is .closed(). I don't close my ResultSet. Whatever the problem is, how can I modify this code so that when I get it, it won't be closed?
PS - Just ignore my old school System.outs...
You close the connection, and that closes the ResultSet.
Instead of storing the ResultSet in a class member, store it in a local variable inside Refunds, and read all the data from it before returning from the Refunds method and closing the connection.

Eclipse - GWT - Java - MySQL - how to catch an exception correctly

I have finally completed my application (Eclipse, GWT, Java, MySQL, Tomcat) and it has been uploaded onto a server (I have someone else uploading the application onto a server). However, there seems to be an issue with the server installation and my code is not sending back any errors.
For instance: when a new account is created the following message is displayed "Your account has been created. Please contact a leader to associate youth members to it." however the database is not updated. It seems that I am not catching an exception correctly.
My code is:
Client side call:
AsyncCallback<User> callback = new CreationHandler<User>();
rpc.createUser(textBoxAccount.getText(), textBoxPassword.getText(), null, null, null, callback);
Server side:
public User createUser(String userName, String pass, String level, String pack, java.sql.Date archived) {
User user = null; // necessary unless you do something in the exception handler
ResultSet result = null;
PreparedStatement ps = null;
String pw_hash = BCrypt.hashpw(pass, BCrypt.gensalt());
try {
ps = conn.prepareStatement(
"INSERT INTO at_accounts (acc_email_address, acc_password, acc_enabled) " +
"VALUES (?, ?, ?)");
ps.setString(1, userName);
ps.setString(2, pw_hash);
ps.setString(3, "1");
ps.executeUpdate();
}
catch (SQLException e) {
//do stuff on fail
System.out.println("SQLException createUser 1.");
e.printStackTrace();
user = null;
}
finally {
if (result != null) {
try {
result.close();
}
catch (SQLException e) {
System.out.println("SQLException createUser 2.");
e.printStackTrace();
}
}
if (ps != null) {
try {
ps.close();
}
catch (SQLException e) {
System.out.println("SQLException createUser 3.");
e.printStackTrace();
}
}
}
return user;
}
Client side:
class CreationHandler<T> implements AsyncCallback<User> {
//Create the account.
public void onFailure(Throwable ex) {
Window.alert("RPC call failed - CreationHandler - Notify Administrator.");
}
public void onSuccess(User result) {
Window.alert("Your account has been created. Please contact a leader to associate youth members to it.");
}
}
Any help would be greatly appreciated.
Regards,
Glyn
Hi JonK,
Is this what you mean please?
public User createUser(String userName, String pass, String level, String pack, java.sql.Date archived) {
User user = null; // necessary unless you do something in the exception handler
ResultSet result = null;
PreparedStatement ps = null;
String pw_hash = BCrypt.hashpw(pass, BCrypt.gensalt());
try {
ps = conn.prepareStatement(
"INSERT INTO at_accounts (acc_email_address, acc_password, acc_enabled) " +
"VALUES (?, ?, ?)");
ps.setString(1, userName);
ps.setString(2, pw_hash);
ps.setString(3, "1");
ps.executeUpdate();
}
catch (SQLException e) {
//do stuff on fail
try {
conn.rollback();
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
System.out.println("SQLException createUser 1.");
e.printStackTrace();
user = null;
}
finally {
if (result != null) {
try {
result.close();
}
catch (SQLException e) {
try {
conn.rollback();
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
System.out.println("SQLException createUser 2.");
e.printStackTrace();
}
}
if (ps != null) {
try {
ps.close();
}
catch (SQLException e) {
try {
conn.rollback();
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
System.out.println("SQLException createUser 3.");
e.printStackTrace();
}
}
}
try {
conn.commit();
} catch (SQLException e) {
try {
conn.rollback();
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
System.out.println("SQLException createUser 4 - commit error.");
e.printStackTrace();
}
return user;
}
This is the updated code with the suggested error handling:
package org.AwardTracker.server;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.sql.Connection;
import java.sql.Date;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import org.AwardTracker.client.BCrypt;
import org.AwardTracker.client.Account;
import org.AwardTracker.client.AccountAndCubs;
import org.AwardTracker.client.AccountCubAssociation;
import org.AwardTracker.client.AwardAward;
import org.AwardTracker.client.AwardDescription;
import org.AwardTracker.client.AwardStockDtls;
import org.AwardTracker.client.DBConnection;
import org.AwardTracker.client.SectionDetails;
import org.AwardTracker.client.Stock;
import org.AwardTracker.client.User;
import org.AwardTracker.client.ViewData;
import org.AwardTracker.client.YMATask;
import org.AwardTracker.client.YMAwards;
import org.AwardTracker.client.YMandAward;
import org.AwardTracker.client.YMAwardDetails;
import org.AwardTracker.client.YouthMember;
import org.AwardTracker.client.YouthMemberAwards;
import org.AwardTracker.client.YthMmbrSectDtls;
import org.AwardTracker.server.Base64Encode2;
public class MySQLConnection extends RemoteServiceServlet implements DBConnection {
//TODO
// •Use JNDI to bind the data source.
// •Close the connection as soon as its done in finally block.
// •Manage the connection in single class for whole application.
// •Initialise the data source at application start up single time.
// •Store the database configuration outside the JAVA code somewhere in properties file or web.xml.
// •Create an abstract class for AsyncCallback that will handle all the failures happened while performing any RPC calls.
// •Extend this abstract class for all RPC AsyncCallback but now you have to just provide implementation of onSuccess() only.
// •Don't handle any exception in service implementation just throw it to client or if handled then re-throw some meaning full exception back to client.
// •Add throws in all the methods for all the RemoteService interfaces whenever needed.
private static final long serialVersionUID = 1L;
private Connection conn = null;
private String url = "jdbc:mysql://localhost/awardtracker";
private String user = "awtrack";
private String pass = "************";
public MySQLConnection() {
try {
Class.forName("com.mysql.jdbc.Driver");
conn = DriverManager.getConnection(url, user, pass);
} catch (Exception e) {
//NEVER catch exceptions like this
System.out.println("Error connecting to database - not good eh");
e.printStackTrace();
}
}
//Store and retrieve data used by Views within the application
//This allows us to securely pass parameters between Views.
private ViewData viewData = null;
public ViewData setViewData(String accountId, String accountLevel,
String ymId, String awId, String adGroup) {
viewData = new ViewData();
viewData.setaccountId(accountId);
viewData.setaccountLevel(accountLevel);
viewData.setymId(ymId);
viewData.setawId(awId);
viewData.setadGroup(adGroup);
return viewData;
}
public ViewData getViewData() {
return viewData;
}
public User authenticateUser(String accID, String userName, String pass, String level, String pack, Integer enabled, java.sql.Date archived) {
User user = null; // necessary unless you do something in the exception handler
ResultSet result = null;
PreparedStatement ps = null;
String stored_hash = null;
try {
ps = conn.prepareStatement(
"SELECT * " +
"FROM at_accounts " +
"WHERE acc_email_address = ?");
ps.setString(1, userName);
result = ps.executeQuery();
while (result.next()) {
user = new User(result.getString(1), result.getString(2), result.getString(3), result.getString(4), result.getString(5), result.getInt(6), result.getDate(7));
stored_hash = result.getString(3);
}
}
catch (SQLException e) {
try {
conn.rollback();
}
catch (SQLException e2) {
System.out.println("Error rolling back transaction for authenticateUser.");
e2.printStackTrace();
}
System.out.println("SQLException in authenticateUser.");
e.printStackTrace();
}
if (stored_hash != null) {
if (BCrypt.checkpw(pass, stored_hash)) {
} else {
user = null;
}
}else{
user = null;
}
return user;
}
//Disable or enable Account
public User disableUser(String user, Integer enabled) {
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(
"UPDATE at_accounts " +
"SET acc_enabled=? " +
"WHERE acc_email_address=?");
ps.setInt(1, enabled);
ps.setString(2, user);
ps.executeUpdate();
conn.commit();
}
catch (SQLException e) {
try {
conn.rollback();
}
catch (SQLException e2) {
System.out.println("Error rolling back transaction for createUser.");
e2.printStackTrace();
}
System.out.println("SQLException in createUser.");
e.printStackTrace();
}
return null;
}
public User duplicateUser(String userName, String pass, String level, String pack, java.sql.Date archived) {
User user = null; // necessary unless you do something in the exception handler
ResultSet result = null;
PreparedStatement ps = null;
try {
ps = conn.prepareStatement(
"SELECT * " +
"FROM at_accounts " +
"WHERE acc_email_address = ?");
ps.setString(1, userName);
result = ps.executeQuery();
while (result.next()) {
user = new User(null, result.getString(2), null, null, null, null, null);
}
}
catch (SQLException e) {
try {
conn.rollback();
}
catch (SQLException e2) {
System.out.println("Error rolling back transaction for duplicateUser.");
e2.printStackTrace();
}
System.out.println("SQLException in duplicateUser.");
e.printStackTrace();
}
return user;
}
public User createUser(String userName, String pass, String level, String pack, java.sql.Date archived) {
PreparedStatement ps = null;
String pw_hash = BCrypt.hashpw(pass, BCrypt.gensalt());
try {
ps = conn.prepareStatement(
"INSERT INTO at_accounts (acc_email_address, acc_password, acc_enabled) " +
"VALUES (?, ?, ?)");
ps.setString(1, userName);
ps.setString(2, pw_hash);
ps.setString(3, "1");
ps.executeUpdate();
conn.commit();
}
catch (SQLException e) {
try {
conn.rollback();
}
catch (SQLException e2) {
System.out.println("Error rolling back transaction for createUser.");
e2.printStackTrace();
}
System.out.println("SQLException in createUser.");
e.printStackTrace();
}
return null;
}
Points to rememeber:
Use JNDI to bind the data source.
Close the connection as soon as its done in finally block.
Manage the connection in single class for whole application.
Initialize the data source at application start up single time.
Store the database configuration outside the JAVA code somewhere in properties file or web.xml.
I have already shared a sample code for ConnectionUtil class that's sole purpose is to manage the connection in single class using JNDI lookup and it can log that how many connections are opened for what time in the application?
Please have a look at below posts:
“Servlet” (server-side) initialization code in GWT
No operations allowed after statement closed
GWT - how to catch an exception correctly?
Create an abstract class for AsyncCallback that will handle all the failures happened while performing any RPC calls.
Extend this abstract class for all RPC AsyncCallback but now you have to just provide implementation of onSuccess() only.
Don't handle any exception in service implantation just throw it to client or if handled then re-throw some meaning full exception back to client.
Add throws in all the methods for all the RemoteService interfaces whenever needed.
Sample code:
// single class to handle all the AsyncCallback failure
public abstract class MyAsyncCallback<T> implements AsyncCallback<T> {
#Override
public void onFailure(Throwable caught) {
// all the failure are catched here
// prompt user if needed
// on failure message goes to here
// send the failure message back to server for logging
}
}
// do it for all the RPC AsyncCallback
public class CreationHandler<T> extends MyAsyncCallback<T> {
//Create the account.
public void onSuccess(T result) {
// on success message goes to here
}
}
// use in this way
AsyncCallback<User> callback = new CreationHandler<User>();
You aren't committing the transaction to the database. In order for the changes made by ps.executeUpdate(); to become permanent, you will need to call conn.commit(); after the update.
Similarly, in your catch block you should call conn.rollback(); so as to avoid the possibility of dud data being inserted into the database.
I can't see the declaration for conn, so I assume it's a member variable whatever class createUser belongs to. You might want to consider changing the Connection to be a local in the method, so that you don't forget to close it once it's no longer needed (which should be once you've committed).
Lastly, if you're using Java 7+, you can take advantage of try-with-resources to handle the closing of your PreparedStatement, ResultSet and Connection for you (although you don't appear to be using the ResultSet for anything, so consider removing it from the method).
Here are two examples of what I meant (one for Java 6 and below, and one for Java 7 and later utilising try-with-resources:
Java 6-
public void createUser(String userName, String pass) {
PreparedStatement ps = null;
Connection conn = null;
String pw_hash = BCrypt.hashpw(pass, BCrypt.gensalt());
try {
// Acquire a Connection here rather than using a member variable
// NOTE: See Braj's answer for a better way of doing this
// using his ConnectionUtil class.
conn = DriverManager.getConnection(
"jdbc:mysql://localhost/awardtracker", "awtrack",
"**************");
ps = conn.prepareStatement(
"INSERT INTO at_accounts (acc_email_address, acc_password,"
+ " acc_enabled) "
+ "VALUES (?, ?, ?)");
ps.setString(1, userName);
ps.setString(2, pw_hash);
ps.setString(3, "1");
ps.executeUpdate();
conn.commit();
} catch (SQLException e) {
try {
conn.rollback();
} catch (SQLException e2) {
System.out.println("Error rolling back transaction.");
e2.printStackTrace();
}
System.out.println("SQLException createUser 1.");
e.printStackTrace();
} finally {
if (ps != null) {
try {
ps.close();
} catch (SQLException e) {
System.out.println("SQLException createUser 3.");
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
System.out.println("Error closing Connection.");
e.printStackTrace();
}
}
}
}
Java 7+
private static final String INSERT_STATEMENT =
"INSERT INTO at_accounts (acc_email_address, acc_password, "
+ "acc_enabled) VALUES (?, ?, ?)";
public void createUser(String userName, String pass) {
String pw_hash = BCrypt.hashpw(pass, BCrypt.gensalt());
// NOTE: See Braj's answer for a better way of getting Connections.
try (Connection conn = DriverManager.getConnection(
"jdbc:mysql://localhost/awardtracker", "awtrack",
"**************");
PreparedStatement ps = conn.prepareStatement(INSERT_STATEMENT);) {
try {
ps.setString(1, userName);
ps.setString(2, pw_hash);
ps.setString(3, "1");
ps.executeUpdate();
conn.commit();
} catch (SQLException e) {
try {
conn.rollback();
} catch (SQLException e2) {
System.out.println("Error rolling back transaction.");
e2.printStackTrace();
}
System.out.println("SQLException createUser 1.");
e.printStackTrace();
}
} catch (SQLException e) {
System.out.println("Error connecting to DB.");
e.printStackTrace();
}
}
In both examples I have removed unused method parameters (why have them there if you're doing nothing with them?) and have changed the return type to void. I did this because in its current form your method will always return null (you initialise your User object to null, then do nothing with it to change its value, then return it at the end).
You should also consider using a logging framework such as log4j to handle your exception logging rather than relying on printStackTrace(). See Why is exception.printStackTrace() considered bad practice? for more information on why printStackTrace() isn't recommended.

Oracle database connection via Java

I have a basic connection to an oracle database, I getting back the first two print statements i.e connecting to the database and reading back the query which is to be inserted but I'm not reaching line updateQuery = statement.executeUpdate(); and therefore the statement isn't executed.
I'm getting no error and I have the ojdbc driver downloaded, any suggestions ?
import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.PreparedStatement;
public class conn1 {
public static void main(String[] argv) {
//Scanner out = new Scanner(String);
//In Java, we use plain JDBC calls to insert a record in STUDENTS table. We use sequence STUDENT_SEQ to generate primary key.
//Once the record is inserted, we want the last inserted primary value.
PreparedStatement statement = null;
int updateQuery = 0;
String QUERY = "INSERT INTO SYS.STUDENTS (student_id, NAME, EMAIL, BIRTH_DATE)"
+ "VALUES ('1','Hermoine', 'Hermoine#hogwarts.edu', '08-Nov-1987')";
// load oracle driver
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
} catch (ClassNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
// get database connection from connection string
Connection connection = null;
try {
connection = DriverManager.getConnection(
"jdbc:oracle:thin:#localhost:1521:attendanced", "louise", "Attend123!");
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
if (connection != null) {
System.out.println("Successfullly connected to Oracle DB");
try {
statement = connection.prepareStatement(QUERY);
System.out.println("Insert This Query :" + QUERY);
updateQuery = statement.executeUpdate(); //Erroneous line.
if (updateQuery != 0) {
System.out.println("Record inserted successfully");
} else {
System.out.println("Error, Record not inserted");
}
} catch (SQLException e) {
e.printStackTrace();
}
} else {
System.out.println("Failed to connect to Oracle DB");
}
}
}

Why the rollback operation is not done after an exception came in my java code

I have a jdbc code in which I have used transaction management in code.
Following is the code.I am using Mysql Database.
public class JdbcConn {
public static void main(String[] args){
Savepoint spt1 = null;
Connection con = null;
try{
Class.forName("org.gjt.mm.mysql.Driver");
con = DriverManager.getConnection("jdbc:mysql://localhost","root","tany");
con.setAutoCommit(false);
spt1= con.setSavepoint("svpt1");
PreparedStatement psmt;
String query1 = "select city, countryid from querytest.city;";
psmt=con.prepareStatement(query1);
ResultSet rs=psmt.executeQuery();
while(rs.next()){
String query2 = "insert into sun.city (city,countryid) values('"+rs.getString(1)+"',"+rs.getInt(2)+");";
psmt=con.prepareStatement(query2);
psmt.executeUpdate();
}
String query3 = "create database `transtest`;";
psmt=con.prepareStatement(query3);
psmt.executeUpdate();
String query4 = "CREATE TABLE `transtest`.`trans` (`id` tinyint(4) NOT NULL auto_increment,`val` int(5) NOT NULL default 0, PRIMARY KEY (`id`)) ENGINE=MyISAM;";
psmt=con.prepareStatement(query4);
psmt.executeUpdate();
String query5 = "CREATE TABLE `transtest`.`transone` (`id` tinyint(4) NOT NULL auto_increment,`val` int(5) NOT NULL default 0, PRIMARY KEY (`id`)) ENGINE=MyISAM;";
psmt=con.prepareStatement(query5);
psmt.executeUpdate();
String query6 = "CREATE TABLE `transtest`.`transtwo` (`id` tinyint(4) NOT NULL auto_increment,`val` int(5) NOT NULL default 0, PRIMARY KEY (`id`)) ENGINE=MyISAM;";
psmt=con.prepareStatement(query6);
psmt.executeUpdate();
for(int i=1;i<=10;i++){
String query7 = "insert into `transtest`.`transtwo` (`val`) values ("+i*2+");";
psmt=con.prepareStatement(query7);
psmt.executeUpdate();
}
String query8 = "insertd into `transtest`.`trans` (`val`) values (500);";
psmt=con.prepareStatement(query8);
psmt.executeUpdate();
JOptionPane.showMessageDialog(null, "Process completed!");
con.commit();
con.setAutoCommit(true);
}catch(SQLException sqle){
try {
con.rollback(spt1);
JOptionPane.showMessageDialog(null, "Rollback1!");
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
sqle.getMessage();
sqle.printStackTrace();
}catch (ClassNotFoundException cnfe) {
// TODO Auto-generated catch block
try {
con.rollback(spt1);
JOptionPane.showMessageDialog(null, "Rollback2!");
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
cnfe.getMessage();
cnfe.printStackTrace();
}catch (Exception e) {
// TODO Auto-generated catch block
try {
con.rollback(spt1);
JOptionPane.showMessageDialog(null, "Rollback3!");
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
e.getMessage();
e.printStackTrace();
}
}
}
This above code is not rolling back when sql exception comes.
The schema of the table in query1 and the schema of the table in query2 is same but as you see the databases are different.
I just dont know if any exception comes why its not rolling back the changes made by the querys from query2 to query7.
I had intensionally made a syntactical mistake in query8 for an exception.
Please guide me friends in this issue and plaease lent me know my mistakes in code.
Thank You!
Here's how I would do it:
Connection con = null;
boolean ok = false;
try {
con = DriverManager.getConnection(...);
...
con.commit();
ok = true;
} catch (...) {
// diagnose exception
}
...
} finally {
if (con != null) {
try {
if (!ok) con.rollback();
} finally {
con.close();
}
}
}
In other words, do the connection close and rollback in the finally block ... and don't repeat the code.
And DON"T catch Exception ... see below.
A comment on the Question says this:
As a general principle, catch Throwable, not just Exception. In fact, catch only Throwable, no need to repeat the blocks. That may even solve your problem.
Catching Exception and especially Throwable is a bad idea UNLESS the next action after handling the exception is to exit the application. There are any number of potential unchecked exceptions / errors that might occur. You've no way of knowing what the cause of the unexpected exception was, or whether the application can safely recover.
But the problem in my code is that its not rolling back the transactions done by the queries from query2 to query7
Perhaps it is because some of those statements are non-transactional (e.g. CREATE TABLE), and executing a non-transactional statement causes the current transaction to commit automatically.
Perhaps it is a problem with the old version of MySQL and the JDBC drivers that you are using. The "org.gjt.mm.mysql" driver is REALLY old, and I know for a fact that early versions of MySQL did not support transactions at all.
As I suspected, you can't rollback a CREATE TABLE in MySQL.
Source:
StackOverflow Q&A Is it possible to roll back CREATE TABLE and ALTER TABLE statements in major SQL databases?
You cannot roll back a create table statement in MySQL, because it will cause an implicit commit. See: Statements That Cause an Implicit Commit

Categories