Создает ли новый оператор из фиксации соединения все, даже если автоматическая фиксация является ложной?
У меня есть следующий код:
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;
где у вас есть h2.jar
в одной папке с App.java
,
1 ответ
Если соединение выполняет вставку, обновление или удаление внутри транзакции, то другие операторы этого же соединения смогут видеть изменения, даже если эти изменения не были зафиксированы, так что другие соединения могут их видеть.
(На самом деле, при нормальных обстоятельствах другие соединения не могут видеть изменения, пока они не будут зафиксированы, но транзакция с уровнем изоляции READ_UNCOMMITTED позволит другим соединениям видеть изменения до того, как исходное соединение выполнит фиксацию или откат.)