1

I'm trying to implement the change in database connection closing suggested in this question's answers. More than once, I've come across this block of code at the end of my try blocks:

try {
    -Code-
} catch(DatabaseException de) {
    if(conn != null)
    try{ 
        conn.rollback(); 
    } catch(SQLException e) { }
    throw de;
} catch(SQLException se) {
    if(conn != null)
    try { 
        conn.rollback(); 
    } catch(SQLException e) { }
    throw new DatabaseException("SQLException caught: "+se.getMessage());
} finally{
    if(conn != null)
    try{ 
        conn.rollback();
        conn.rollback();
        conn.close(); 
    } catch(SQLException e) { }
}

This absolutely baffles me - why would we need to rollback our connection twice before closing it in a Finally block, when we're already catching the rollback separately?

  • 1
    There isn't enough code here to make the question answerable, but it looks like the author of that code is catching every possible exception at every possible time an exception might be thrown. This is part of the curse of checked exceptions; it would be better to simply catch exception. The catch in the finally block is there to guarantee that the rollback occurs if it is needed. Kinda like mashing the mouse button harder to get a better result. – Robert Harvey Jun 10 '15 at 19:35
  • 2
    @RobertHarvey I think the OP is asking about the two consecutive rollbacks in the finally block. They seem like a cut-and-pase mistake to me... – Andres F. Jun 10 '15 at 19:42
  • @AndresF. That is exactly what I'm asking about. – Zibbobz Jun 10 '15 at 19:49
  • 1
    Ah. No good reason for that at all. Remove second one, problum solved. That really is like mashing the mouse button harder. – Robert Harvey Jun 10 '15 at 20:10
  • 2
    They probably are. But there's more bad stuff going on here than just mashing the mouse button twice. Like the checked exceptions, for example. – Robert Harvey Jun 10 '15 at 20:13
2

I have seen this code before in another language (Delphi). It was implemented that way because of an issue where the database (in this case Oracle 7 or 8) wouldn't reliably rollback the first time the rollback method was called. The bug was seemingly random and could not be reliably reproduced - even in production.

Rather than spending days tracking down the Heisenbug the developer decided to put a second rollback in which "fixed" the problem. We made sure that this was properly commented to document the hack.

IIRC moving to directly use the Oracle Call Interface rather than the Borland Database Engine resolved the issue which points to the problem being something weird in the database abstraction layer.

  • So if I'm reading this correctly: You've seen where this is used to bypass janky Oracle coding that fails to rollback on the first try? And if that's the case here, then the issue is almost certainly at the SQL level, rather than the app level? – Zibbobz Jun 11 '15 at 13:09
  • I'm loathe to pin it purely on Oracle. It could have been a dodgy network or, more likely, a problem in the BDE and the way it interfaced with Oracle - which is always going to be a potential issue with lowest common denominator frameworks... As I said, when we changed the interface library the problem went. DOA (Direct Oracle Access) for the win BTW. – mcottle Jun 12 '15 at 1:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.