#sql #jdbc #transactions #commit #h2db
#sql #jdbc #транзакции #фиксирует #h2db
Вопрос:
У меня есть следующий код:
import java.sql.*;
class App {
public static void main(String[] args) {
HelloJdbc hj = new HelloJdbc();
hj.insertPerson();
hj.printPersons();
hj.close();
}
}
class HelloJdbc {
String url = "jdbc:h2:~/persons";
String username = "username";
String password = "password";
// Active connection
Connection con;
public HelloJdbc() {
try {
Connection con = DriverManager.getConnection(url, username, password); Statement st = con.createStatement();
// Making sure I have the same data every time
st.executeUpdate("DELETE FROM person");
st.executeUpdate("INSERT INTO person VALUES (1, 'Alice');");
this.con = con;
} catch (SQLException e) {}
}
void insertPerson() {
try {
con.setAutoCommit(false);
con.createStatement().executeUpdate("INSERT INTO person VALUES(2, 'Bob');");
} catch (SQLException e) {}
}
void printPersons() {
try (Connection con = DriverManager.getConnection(url, username, password);) {
ResultSet rs = con.createStatement().executeQuery("SELECT * FROM person;");
while (rs.next()) {
System.out.println(rs.getObject(1) " " rs.getObject(2));
}
} catch (SQLException e) {}
}
void close() {
try {
con.close();
} catch (Exception e) {}
}
}
Когда я запускаю этот код, вывод будет:
1 Alice
Это я понимаю, поскольку в insertPerson
у меня есть con.setAutoCommit(false);
Однако, когда я меняю printPerson
метод следующим образом, чтобы вместо нового соединения использовалось активное соединение:
void printPersons() {
try {
ResultSet rs = con.createStatement().executeQuery("SELECT * FROM person;");
while (rs.next()) {
System.out.println(rs.getObject(1) " " rs.getObject(2));
}
} catch (SQLException e) {}
}
Выходные данные изменяются на:
1 Alice
2 Bob
Я в замешательстве, фиксирует ли создание нового оператора из соединения все из предыдущего оператора? В чем причина изменения поведения?
Скомпилируйте и запустите с помощью javac App.java; java -cp ".:h2.jar" App;
where у вас есть h2.jar
в той же папке с App.java
.
Ответ №1:
Если соединение выполняет вставку, обновление или удаление внутри транзакции, то другие операторы этого того же соединения смогут видеть изменения, даже если эти изменения не были зафиксированы, чтобы их могли видеть другие соединения.
(На самом деле, при нормальных обстоятельствах другие соединения не могут видеть изменения, пока они не будут зафиксированы, но транзакция с уровнем изоляции READ_UNCOMMITTED позволит другим соединениям увидеть изменения до того, как исходное соединение выполнит фиксацию или откат.)