Транзакция JDBC в Java
По умолчанию SQLite фиксирует каждый запрос отдельно.
Флаг autoCommit = false на Connection
складывает шаги в одну транзакцию до явного
commit или rollback.
Два успешных INSERT попадут на диск только
после commit:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.Statement;
public class Main {
public static void main(String[] args) throws Exception {
try (Connection connection = DriverManager.getConnection("jdbc:sqlite:txn_ok.db")) {
connection.autoCommit = false;
try (Statement statement = connection.createStatement()) {
statement.execute("""
CREATE TABLE IF NOT EXISTS moves (
id INTEGER PRIMARY KEY,
step TEXT NOT NULL
)
""");
}
try {
PreparedStatement first = connection.prepareStatement(
"INSERT INTO moves (step) VALUES (?)"
);
first.setString(1, "load");
first.executeUpdate();
PreparedStatement second = connection.prepareStatement(
"INSERT INTO moves (step) VALUES (?)"
);
second.setString(1, "seal");
second.executeUpdate();
connection.commit();
} catch (Exception ex) {
connection.rollback();
throw ex;
}
}
}
}
}
При ошибке между шагами rollback отменяет
несохранённые изменения в рамках транзакции:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
public class Main {
public static void main(String[] args) throws Exception {
try (Connection connection = DriverManager.getConnection("jdbc:sqlite:txn_fail.db")) {
connection.autoCommit = false;
try (Statement statement = connection.createStatement()) {
statement.execute("""
CREATE TABLE IF NOT EXISTS moves (
id INTEGER PRIMARY KEY,
step TEXT NOT NULL
)
""");
}
try {
PreparedStatement insert = connection.prepareStatement(
"INSERT INTO moves (step) VALUES (?)"
);
insert.setString(1, "start");
insert.executeUpdate();
throw new RuntimeException("stop");
} catch (Exception ignored) {
connection.rollback();
}
try (Statement countStatement = connection.createStatement();
ResultSet count = countStatement.executeQuery(
"SELECT COUNT(*) AS c FROM moves",
)) {
if (count.next()) {
System.out.println(count.getInt("c"));
}
}
}
}
}
}
Создайте таблицу ledger_tx в bank.db
с полем note, выполните два добавления
в одной транзакции и зафиксируйте их.
Повторите два добавления, но вызовите откат перед
фиксацией и выведите 0 строк в таблице.