Java: commit vs rollback vs nothing when semantics is unchanged? - java

Ok, I know the difference between commit and rollback and what these operations are supposed to do.
However, I am not certain what to do in cases where I can achieve the same behavior when using commit(), rollback() and/or do nothing.
For instance, let's say I have the following code which executes a query without writing to db:
I am working on an application which communicates with SQLite database.
try {
doSomeQuery()
// b) success
} catch (SQLException e) {
// a) failed (because of exception)
}
Or even more interesting, consider the following code, which deletes a single row:
try {
if (deleteById(2))
// a) delete successful (1 row deleted)
else
// b) delete unsuccessful (0 row deleted, no errors)
} catch (SQLException e) {
// c) delete failed (because of an error (possibly due to constraint violation in DB))
}
Observe that from a semantic standpoint, doing commit or rollback in cases b) and c) result in the same behavior.
Generally, there are several choices to do inside each case (a, b, c):
commit
rollback
do nothing
Are there any guidelines or performance benefits of choosing a particular operation? What is the right way?
Note: Assume that auto-commit is disabled.

If it is just a select, I wouldn't open a transaction and therefore, there is nothing to do in any case. Probably you already know is there is an update/insert since you have already passed the parameters.
The case where you intend to do a manipulation is more interesting. The case where it deletes is clear you want to commit; if there is an exception you should rollback to keep the DB consistent since something failed and there is not a lot you can do. If the delete failed because there was nothing to delete I'd commit for 3 reasons:
Semantically, it seems more correct since the operation was
technically successful and performed as specified.
It is more future proof so if somebody adds more code to the
transaction they won't be surprised with it is rolling back because
one delete just didn't do anything (they would expect on exception
that the transaction is rolled back)
When there is an operation to do, commit is faster but in this case I
don't think it matters.

Any non-trivial application will have operations requiring multiple SQL statements to complete. Any failure happening after the first SQL statement and before the last SQL statement will cause data to be inconsistent.
Transactions are designed to make multiple-statement operations as atomic as the single-statement operations you are currently working with.

I've asked myself the exact same question. In the end I went for a solution where I always commited successful transactions and always rollbacked non-successful transactions regardles of it having any effect. This simplified lot of code and made it clearer and more easy to read.
It did not have any major performance problems in the application I worked in which used NHibernate + SQLite on .net. Your milage may vary.

As others stated in their answers, it's not a matter of performance (for the equivalent cases you described), which I believe is negligible, but a matter of maintainability, and this is ever so important!
In order for your code to be nicely maintainable, I suggest (no matter what) to always commit at the very bottom of your try block and to always close your Connection in your finally block. In the finally block you also should rollback if there are uncommitted transactions (meaning that you didn't reach the commit at the end of the try block).
This example shows what I believe is the best practice (miantainability-wise):
public boolean example()
{
Connection conn;
...
try
{
...
//Do your SQL magic (that can throw exceptions)
...
conn.commit();
return true;
}
catch(...)
{
...
return false;
}
finally
{//Close statements, connections, etc
...
closeConn(conn);
}
}
public static void closeConn(Connection conn)
{
if (conn != null)
if (!conn.isClosed())
{
if (!conn.getAutoCommit())
conn.rollback();//If we need to close() but there are uncommitted transacitons (meaning there have been problems)
conn.close();
conn = null;
}
}

What you are saying depends upon the code being called, does it return a flag for you to test against, or does it exclusively throw exceptions if something goes wrong?
API throws exceptions but also returns a boolean (true|false):
This situation occurs a lot, and it makes it difficult for the calling code to handle both conditions, as you pointed out in your OP. The one thing you can do in this situation is:
// Initialize a var we can test against later
// Lol, didn't realize this was for java, please excuse the var
// initialization, as it's demonstrative only
$queryStatus = false;
try {
if (deleteById(2)) {
$queryStatus = true;
} else {
// I can do a few things here
// Skip it, because the $queryStatus was initialized as false, so
// nothing changes
// Or throw an exception to be caught
throw new SQLException('Delete failed');
}
} catch (SQLException $e) {
// This can also be skipped, because the $queryStatus was initialized as
// false, however you may want to do some logging
error_log($e->getMessage());
}
// Because we have a converged variable which covers both cases where the API
// may return a bool, or throw an exception we can test the value and determine
// whether rollback or commit
if (true === $queryStatus) {
commit();
} else {
rollback();
}
API exclusively throws exceptions (no return value):
No problem. We can assume that if no exception was caught, the operation completed without error and we can add rollback() / commit() within the try/catch block.
try {
deleteById(2);
// Because the API dev had a good grasp of error handling by using
// exceptions, we can also do some other calls
updateById(7);
insertByName('Chargers rule');
// No exception thrown from above API calls? sweet, lets commit
commit();
} catch (SQLException $e) {
// Oops exception was thrown from API, lets roll back
rollback();
}
API does not throw any exceptions, only returns a bool (true|false):
This goes back to old school error handling/checking
if (deleteById(2)) {
commit();
} else {
rollback();
}
If you have multiple queries making up the transaction, you can borrow the single var idea from scenario #1:
$queryStatus = true;
if (!deleteById(2)) {
$queryStatus = false;
}
if (!updateById(7)) {
$queryStatus = false;
}
...
if (true === $queryStatus) {
commit();
} else {
rollback();
}
"Note: Assume that auto-commit is disabled."
Once you disable auto-commit, you are telling the RDBMS that you are taking control of commits from now until auto-commit is re-enabled, so IMO, it's good practice to either rollback or commit the transaction versus leaving any queries in limbo.

Related

Executing sql statement from schema.sql file in ContextInitializer method

I am trying to execute a sql statement in Listener's contextInitialized method, but when I run gretty local server, it throws RuntimeException error. I can't figure out, why. It doesn't run into any errors when i comment out ps.executeQuery();.
#Override
public void contextInitialized(ServletContextEvent sce){
ServletContext sc = sce.getServletContext();
DataSource pool = new ConnectionPoolFactory().createConnectionPool();
String sql = "create table test (id int);";
try (Connection conn = pool.getConnection();
PreparedStatement ps = conn.prepareStatement(sql)) {
ps.executeQuery();
} catch (SQLException e) {
throw new RuntimeException();
}
}
"Doctor, it hurts when I press here!"
Well, stop doing that then.
This:
} catch (SQLException e) {
throw new RuntimeException();
}
is in a word insane. You're taking a useful error which includes 5 convenient aspects that will help you figure out what went wrong:
The actual type of the exception (Could be a subclass of SQLException; 'DatabaseNotAvailableException', for example)
The message associated with it
The stack trace which points precisely at the line of code that caused it
The cause - exceptions can have causes, which are themselves exceptions (well, throwables). The cause is often more useful than the exception itself.
The chain of swallowed exceptions. This is rarely useful.
You've decided to pitch them all into the garbage, to replace it with a single RuntimeException that gives no useful information of any sort or kind whatsoever.
Do not do that.
Proper exception handling involves being a lot less scared of the throws clause on methods. Got a method that does DB stuff, and the design of this method is clearly indicated to do so (if the method is named 'query' or otherwise contains any word that obviously indicates SQL, the answer is clearly: Yes, it does), then that method should be declared to throws SQLException, for example.
Secondarily, in the rare cases where throwing it onwards does not work out, if you catch an exception, you do not want to just log it and continue, and you do not want to throw some other exception without setting up a cause first. This is the standard 'I do not know what to do and I do not want to spend any further time on thinking about it' exception handler:
} catch (ThingIDoNotWantToThinkAbout e) {
throw new RuntimeException("Unhandled", e);
}
That , e is crucial, it sets up the actual exception as cause, so that you actually see it in your stack traces and logs. It is very common to see a standard exception handling of e.printStackTrace(). Do not do this - 90% of java examples are bad. This causes all sorts of problems, because the 'logs' go to standarderr (which is a lot less flexible than letting them go to the exception handler of the context within which you are operating. For example, if writing a web handler, e.printStackTrace() just dumps stack. Throwing an exception upwards will dump stack and allow the framework to add information about the request that triggered the problem, and serve up a suitable HTTO status 500 error page. Also, by just running printStackTrace, the code will continue execution, which is obviously not what you want: Something went wrong - continuing blindly onward will either guarantee that your software silently does the wrong thing, or causes further exceptions, thus resulting in a single error causing hundreds of stack traces flooding your syserr.
Once you've fixed this problem here and everywhere else in your code, the actual problem will most likely be clear as day. Something about the SQL server being down or a syntax error in your SQL.

Why Catching Throwable or Error is bad? [duplicate]

Is it a bad practice to catch Throwable?
For example something like this:
try {
// Some code
} catch(Throwable e) {
// handle the exception
}
Is this a bad practice or we should be as specific as possible?
You need to be as specific as possible. Otherwise unforeseen bugs might creep away this way.
Besides, Throwable covers Error as well and that's usually no point of return. You don't want to catch/handle that, you want your program to die immediately so that you can fix it properly.
This is a bad idea. In fact, even catching Exception is usually a bad idea. Let's consider an example:
try {
inputNumber = NumberFormat.getInstance().formatNumber( getUserInput() );
} catch(Throwable e) {
inputNumber = 10; //Default, user did not enter valid number
}
Now, let's say that getUserInput() blocks for a while, and another thread stops your thread in the worst possible way ( it calls thread.stop() ). Your catch block will catch a ThreadDeath Error. This is super bad. The behavior of your code after catching that Exception is largely undefined.
A similar problem occurs with catching Exception. Maybe getUserInput() failed because of an InterruptException, or a permission denied exception while trying to log the results, or all sorts of other failures. You have no idea what went wrong, as because of that, you also have no idea how to fix the problem.
You have three better options:
1 -- Catch exactly the Exception(s) you know how to handle:
try {
inputNumber = NumberFormat.getInstance().formatNumber( getUserInput() );
} catch(ParseException e) {
inputNumber = 10; //Default, user did not enter valid number
}
2 -- Rethrow any exception you run into and don't know how to handle:
try {
doSomethingMysterious();
} catch(Exception e) {
log.error("Oh man, something bad and mysterious happened",e);
throw e;
}
3 -- Use a finally block so you don't have to remember to rethrow:
Resources r = null;
try {
r = allocateSomeResources();
doSomething(r);
} finally {
if(r!=null) cleanUpResources(r);
}
Also be aware that when you catch Throwable, you can also catch InterruptedException which requires a special treatment. See Dealing with InterruptedException for more details.
If you only want to catch unchecked exceptions, you might also consider this pattern
try {
...
} catch (RuntimeException exception) {
//do something
} catch (Error error) {
//do something
}
This way, when you modify your code and add a method call that can throw a checked exception, the compiler will remind you of that and then you can decide what to do for this case.
straight from the javadoc of the Error class (which recommends not to catch these):
* An <code>Error</code> is a subclass of <code>Throwable</code>
* that indicates serious problems that a reasonable application
* should not try to catch. Most such errors are abnormal conditions.
* The <code>ThreadDeath</code> error, though a "normal" condition,
* is also a subclass of <code>Error</code> because most applications
* should not try to catch it.
* A method is not required to declare in its <code>throws</code>
* clause any subclasses of <code>Error</code> that might be thrown
* during the execution of the method but not caught, since these
* errors are abnormal conditions that should never occur.
*
* #author Frank Yellin
* #version %I%, %G%
* #see java.lang.ThreadDeath
* #since JDK1.0
It's not a bad practice if you absolutely cannot have an exception bubble out of a method.
It's a bad practice if you really can't handle the exception. Better to add "throws" to the method signature than just catch and re-throw or, worse, wrap it in a RuntimeException and re-throw.
Catching Throwable is sometimes necessary if you are using libraries that throw Errors over-enthusiastically, otherwise your library may kill your application.
However, it would be best under these circumstances to specify only the specific errors thrown by the library, rather than all Throwables.
The question is a bit vague; are you asking "is it OK to catch Throwable", or "is it OK to catch a Throwable and not do anything"? Many people here answered the latter, but that's a side issue; 99% of the time you should not "consume" or discard the exception, whether you are catching Throwable or IOException or whatever.
If you propagate the exception, the answer (like the answer to so many questions) is "it depends". It depends on what you're doing with the exception—why you're catching it.
A good example of why you would want to catch Throwable is to provide some sort of cleanup if there is any error. For example in JDBC, if an error occurs during a transaction, you would want to roll back the transaction:
try {
…
} catch(final Throwable throwable) {
connection.rollback();
throw throwable;
}
Note that the exception is not discarded, but propagated.
But as a general policy, catching Throwable because you don't have a reason and are too lazy to see which specific exceptions are being thrown is poor form and a bad idea.
Throwable is the base class for all classes than can be thrown (not only exceptions). There is little you can do if you catch an OutOfMemoryError or KernelError (see When to catch java.lang.Error?)
catching Exceptions should be enough.
it depends on your logic or to be more specific to your options / possibilities. If there is any specific exception that you can possibly react on in a meaningful way, you could catch it first and do so.
If there isn't and you're sure you will do the same thing for all exceptions and errors (for example exit with an error-message), than it is not problem to catch the throwable.
Usually the first case holds and you wouldn't catch the throwable. But there still are plenty of cases where catching it works fine.
Although it is described as a very bad practice, you may sometimes find rare cases that it not only useful but also mandatory. Here are two examples.
In a web application where you must show a meaning full error page to user.
This code make sure this happens as it is a big try/catch around all your request handelers ( servlets, struts actions, or any controller ....)
try{
//run the code which handles user request.
}catch(Throwable ex){
LOG.error("Exception was thrown: {}", ex);
//redirect request to a error page.
}
}
As another example, consider you have a service class which serves fund transfer business. This method returns a TransferReceipt if transfer is done or NULL if it couldn't.
String FoundtransferService.doTransfer( fundtransferVO);
Now imaging you get a List of fund transfers from user and you must use above service to do them all.
for(FundTransferVO fundTransferVO : fundTransferVOList){
FoundtransferService.doTransfer( foundtransferVO);
}
But what will happen if any exception happens? You should not stop, as one transfer may have been success and one may not, you should keep go on through all user List, and show the result to each transfer. So you end up with this code.
for(FundTransferVO fundTransferVO : fundTransferVOList){
FoundtransferService.doTransfer( foundtransferVO);
}catch(Throwable ex){
LOG.error("The transfer for {} failed due the error {}", foundtransferVO, ex);
}
}
You can browse lots of open source projects to see that the throwable is really cached and handled. For example here is a search of tomcat,struts2 and primefaces:
https://github.com/apache/tomcat/search?utf8=%E2%9C%93&q=catch%28Throwable
https://github.com/apache/struts/search?utf8=%E2%9C%93&q=catch%28Throwable
https://github.com/primefaces/primefaces/search?utf8=%E2%9C%93&q=catch%28Throwable
Generally speaking you want to avoid catching Errors but I can think of (at least) two specific cases where it's appropriate to do so:
You want to shut down the application in response to errors, especially AssertionError which is otherwise harmless.
Are you implementing a thread-pooling mechanism similar to ExecutorService.submit() that requires you to forward exceptions back to the user so they can handle it.
Throwable is the superclass of all the errors and excetions.
If you use Throwable in a catch clause, it will not only catch all exceptions, it will also catch all errors. Errors are thrown by the JVM to indicate serious problems that are not intended to be handled by an application. Typical examples for that are the OutOfMemoryError or the StackOverflowError. Both are caused by situations that are outside of the control of the application and can’t be handled. So you shouldn't catch Throwables unless your are pretty confident that it will only be an exception reside inside Throwable.
If we use throwable, then it covers Error as well and that's it.
Example.
public class ExceptionTest {
/**
* #param args
*/
public static void m1() {
int i = 10;
int j = 0;
try {
int k = i / j;
System.out.println(k);
} catch (Throwable th) {
th.printStackTrace();
}
}
public static void main(String[] args) {
m1();
}
}
Output:
java.lang.ArithmeticException: / by zero
at com.infy.test.ExceptionTest.m1(ExceptionTest.java:12)
at com.infy.test.ExceptionTest.main(ExceptionTest.java:25)
A more differentiated answer would be: it depends.
The difference between an Exception and an Error is that an Exception is a state that has to be expected, while an Error is an unexpected state, which is usually fatal. Errors usually cannot be recovered from and require resetting major parts of the program or even the whole JVM.
Catching Exceptions is something you should always do to handle states that are likely to happen, which is why it is enforced by the JVM. I.E. opening a file can cause a FileNotFoundException, calling a web resource can result in a TimeoutException, and so on. Your code needs to be prepared to handle those situations as they can commonly occur. How you handle those is up to you, there is no need to recover from everything, but your application should not boot back to desktop just because a web-server took a little longer to answer.
Catching Errors is something you should do only if it is really necessary. Generally you cannot recover from Errors and should not try to, unless you have a good reason to. Reasons to catch Errors are to close critical resources that would otherwise be left open, or if you i.E. have a server that runs plugins, which can then stop or restart the plugin that caused the error. Other reasons are to log additional information that might help to debug that error later, in which case you of course should rethrow it to make sure the application terminates properly.
Rule of thumb: Unless you have an important reason to catch Errors, don't.
Therefore use catch (Throwable t) only in such really important situation, otherwise stick to catch (Exception e)

Java - How can I avoid using try catch statements

I would like to know how I can avoid try-catch statements. Right now I have a Database handler and every time I run a command I have to surround it in a try block like so:
try {
while(levelData.next()) {
if(levelData.getInt("level") == nextLevel) return levelData.getInt("exp");
}
} catch (SQLException e) {
e.printStackTrace();
}
Can I make it so the actual function throws the exception or something? Rather than having to manually put all these try's in? Its mostly just an aesthetic problem as these try blocks look ugly.
You can throw an exception instead:
public void myMethod() throws SQLException {
while(levelData.next()) {
if(levelData.getInt("level") == nextLevel)
return levelData.getInt("exp");
}
}
Right now I have a Database handler and every time I run a command I
have to surround it in a try block like so...
I think other answers fail to address the above problems. When I started programming with Java, I hated it when my program was filled with try-catch blocks for SQL query statements.
The way I work around it is to use a DAO-level-layer to handle the exceptions. For example, If my program need to access a User table, I create a UserDAO class. Then the queries are created and exceptions are caught in that DAO class.
Every time an exception occurs, I do the logging needed and throw a custom-specified Unchecked Exception, e.g. DatabaseErrorException. The main difference between an unchecked exception and a checked exception (like SQLException) is that you aren't forced to catch or throw it, so it will not fill your code with the throws statement.
(Yes, you can use throws to avoid using try-catch, but you must handle it somewhere anyway, and think about your functions having throws everywhere.)
Then we can have a global filter at the highest level of the application to catch all these exceptions which propagate through the program. Usually a database error can't be recovered from, so here we only need to display the error to the users.
You can make a method throw an exception with the throws keyword, rather than using a try- catch block, but at some point the exception needs to be handled. What I have found most annoying is multiple catch statements, but if you use JDK >= 1.7 they have a multi-catch option available. For exception logging you can use the log4j library.

How to Continue bulk inserts when exception occurs

I am using jpa with hibernate I want to insert 100 record in Database, suppose I get exception JDBC batch update in 50th record insertion i need to handling the Exception and I need to persist remaining record to DB.
Code:
private List<TempCustomers> tempCustomer =new ArrayList<TempCustomers>();
public String migrateCustomers() {
TempCustomers temp = null;
for(DoTempCustomers tempCustomers:doTempCustomers){
try {
temp=new TempCustomers();
BeanUtils.copyProperties(temp, tempCustomers);
tempCustomer.add(temp);
entityManager.persist(temp);
}catch (Exception e) {
tempCustomer.add(temp);
entityManager.persist(temp);
log.info("Exception ..."+e);
return "null";
}
}
return "null";
}
Nagendra.
What Mr. RAS is telling is correct.
For example you are persisting 100 entities and exception happened in the 50th Entity persist. You have exception handler it will work for you to handle the situation. It ll skip the current one and process the next one.
Things to take care as follows:
1- Your exception handling should be within the loop, hope you already have it.
2- For exception you can save the entity in different list for further analysis for error details. do it in the exception catch block.
3- I am not sure whether you are using the transaction manager or not, transaction need to take care.
--
In the 2nd case please remove the line...
entityManager.persist(temp);
as you already know this throws exception. keep it in the list for your further analysis. better put into any queue(ActiveMQ) upto you.
Best solution for this is again:
Validate all your data before persist...to minimize the exception. runtime things need your re-processing again and that should be manual.

Inserting or updating multiple records in database in a multi-threaded way in java

I am updating multiple records in database. Now whenever UI sends the list of records to be updated, I have to just update those records in database. I am using JDBC template for that.
Earlier Case
Earlier what I was whenever I got records from UI, I just do
jdbcTemplate.batchUpdate(Query, List<object[]> params)
Whenever there was an exception, I used to rollback whole transaction.
(Updated : Is batchUpdate multi-threaded or faster than batch update in some way?)
Later Case
But later as requirement changed whenever there was exception. So, whenever there is some exception, I should know which records failed to update. So I had to sent the records back to UI in case of exception with a reason, why did they failed.
so I had to do something similar to this:
for(Record record : RecordList)
{
try{
jdbcTemplate.update(sql, Object[] param)
}catch(Exception ex){
record.setReason("Exception : "+ex.getMessage());
continue;
}
}
So am I doing this in right fashion, by using the loop?
If yes, can someone suggest me how to make it multi-threaded.
Or is there anything wrong in this case.
To be true, I was hesitating to use try catch block inside the loop :( .
Please correct me, really need to learn a better way because I myself feel, there must be a better way , thanks.
make all update-operation to a Collection Callable<>,
send it to java.util.concurrent.ThreadPoolExecutor. the pool is multithreaded.
make Callable:
class UpdateTask implements Callable<Exception> {
//constructor with jdbctemplate,sql,param goes here.
#Override
public Exception call() throws Exception {
try{
jdbcTemplate.update(sql, Object[] param)
}catch(Exception ex){
return ex;
}
return null;
}
invoke call:
<T> List<Future<T>> java.util.concurrent.ExecutorService.invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException
Your case looks like you need to use validation in java and filter out the valid data alone and send to the data base for updating.
BO layer
-> filter out the Valid Record.
-> Invalid Record should be send back with some validation text.
In DAO layer
-> batch update your RecordList
This will give you the best performance.
Never use database insert exception as a validation mechanism.
Exceptions are costly as the stack trace has to be created
Connection to database is another costly process and will take time to get a connection
Java If-Else will run much faster for same data-base validation

Categories

Resources