Question 1
`setAutoCommit` is never called anywhere in this application. ```java static void transfer(String url) throws SQLException { try (Connection conn = DriverManager.getConnection(url); Statement st = conn.createStatement()) { st.executeUpdate("INSERT INTO ledger VALUES (1, -50)"); st.executeUpdate("INSERT INTO ledger VALUES (2, 50)"); conn.commit(); } } ``` Both INSERT statements succeed. According to the `java.sql.Connection` contract, what happens?
A. The commit() call throws SQLException, and because the transaction never completed, both inserts are rolled back when the connection closes.
Wrong: this spots the exception but reasons that a failed transaction must roll back. There was no open transaction to roll back - both rows were already committed, one per statement, in auto-commit mode.
B. Each insert was already committed as it completed, because new connections start in auto-commit mode; the commit() call then throws SQLException, because commit() may not be called on a connection in auto-commit mode.Correct answer
Correct: new connections start in auto-commit mode, so each insert commits as it completes, and Connection.commit() is specified to throw SQLException when called on a connection in auto-commit mode.
C. Each insert was already committed as it completed, and the commit() call is simply a harmless no-op.
Wrong: this gets the auto-commit default right but assumes a redundant commit() is tolerated. Unlike setAutoCommit, whose Javadoc blesses the redundant case, commit() is specified to throw in auto-commit mode.
D. Neither insert is durable until commit() runs, which then makes both permanent as a single atomic transaction.
Wrong: this is the classic misconception that auto-commit defaults to false and JDBC gives a free transaction. It is exactly backwards - each insert is already durable on completion, and there is no atomicity here.
Explanation
The method never calls `setAutoCommit(false)`, and the `Connection` Javadoc is unambiguous about the starting state: "By default, new connections are in auto-commit mode." In that mode each statement is its own transaction — the Javadoc says the commit "occurs when the statement completes", and for DML "the statement is complete as soon as it has finished executing". So the first INSERT is permanent before the second one even begins. There is no atomicity here at all: this code cannot transfer money safely, which is the real bug the question is pointing at. Then `conn.commit()` runs, and it does not quietly do nothing. `Connection.commit()` documents "This method should be used only when auto-commit mode has been disabled", and lists among its throws: SQLException if "this Connection object is in auto-commit mode". So the call is an error, and the method exits by throwing. Crucially, that thrown exception cannot undo anything — the two rows were committed on completion, and no amount of failure afterwards takes them back. Why the others are wrong: `Neither insert is durable until commit() runs...` is the single most common JDBC misconception: that auto-commit defaults to false and JDBC gives you a transaction for free. It is exactly backwards. If this were true the method would be correct, which is presumably why it was written this way. `Each insert was already committed as it completed, and the commit() call is simply...` gets the auto-commit default right but then assumes a redundant `commit()` is tolerated. Compare `setAutoCommit`, where the Javadoc explicitly blesses the redundant case ("If setAutoCommit is called and the auto-commit mode is not changed, the call is a no-op") — `commit()` gets no such licence; it is specified to throw. `The commit() call throws SQLException, and because the transaction never completed...` spots the exception but then reasons that a failed transaction must roll back. There was no open transaction to roll back — both rows were already committed, one per statement. One caveat worth knowing, because it bites in real code: `commit()` throwing here is what the *contract* requires, and drivers vary in how strictly they enforce it. PostgreSQL and MySQL throw as specified; H2 accepts the redundant call and returns normally. The exam tests the contract, and so should you -- code that relies on a lenient driver breaks the day it moves. Exam tip: a fresh `Connection` is in auto-commit mode, so `commit()` and `rollback()` are BOTH errors until you call `setAutoCommit(false)` first. Watch for the reverse trap too: switching auto-commit off mid-flight is not free — `setAutoCommit` commits any transaction currently in progress.