Фиксирует ли создание нового оператора из соединения все, даже если значение автоматической фиксации равно false?

#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 позволит другим соединениям увидеть изменения до того, как исходное соединение выполнит фиксацию или откат.)