Создает ли новый оператор из фиксации соединения все, даже если автоматическая фиксация является ложной? - PullRequest
0 голосов
/ 02 марта 2019

У меня есть следующий код:

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 Ответ

0 голосов
/ 02 марта 2019

Если соединение выполняет вставку, обновление или удаление внутри транзакции, другие операторы этого того же соединения смогут увидеть изменения, даже если эти изменения не были зафиксированы, поэтому другие соединения могут их видеть.

(На самом деле, при нормальных обстоятельствах другие соединения не могут видеть изменения, пока они не зафиксированы, но транзакция с уровнем изоляции READ_UNCOMMITTED позволит другим соединениям видеть изменения до того, как исходное соединение выполнит фиксацию или откат.)

...