簡體   English   中英

H2事務總是自動提交為什么?

[英]H2 transactions always automatically commit why?

我的應用程序只有 java 和 maven (沒有其他框架)

在 pom.xml 中,我依賴於 H2 數據庫:

 <dependencies>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>1.4.199</version>
        </dependency>
    </dependencies>

我以這種方式創建了一個連接,您可以看到我將 autocommit 設置為 false。 我的 H2 數據庫位於 memory 中。

public class ConnectionManager {

    public static Connection getConnectionManager() throws SQLException {

        Properties myProp = new Properties();
        myProp.put("user"    , "sa");
        myProp.put("password", "");
        myProp.put("autocommit", "false");

       return DriverManager.getConnection("jdbc:h2:mem:test", myProp);
    }

    public static void closeConnection(Connection connection) throws SQLException {
        connection.close();
    }

}

我創建了示例表:

public class InitDatabaseManager {

        private static final String CREATE_TABLE_SQL =
                "CREATE TABLE IF NOT EXISTS users ("
                + "ID INT NOT NULL AUTO_INCREMENT,"
                + "EMAIL VARCHAR(45) NOT NULL,"
                + "PRIMARY KEY (ID))";

        private static final String DROP_TABLE_USERS = "drop table if exists users;";

        public static void initStarterTable (Connection connection) throws SQLException {
            Statement stmt = connection.createStatement();
            stmt.executeUpdate(DROP_TABLE_USERS);
            stmt.executeUpdate(CREATE_TABLE_SQL);
        }
    }

我的問題是為什么在下面的代碼中我插入到 H2 數據庫的記錄雖然我禁用了自動提交?

 public static void insertUsers(Connection connection) throws SQLException {

    connection.setAutoCommit(false);

    System.out.println("[INSERT]");

    String sqlInsert1 = "INSERT INTO users (email) VALUES ('user@mail.com');";
    PreparedStatement psInsert = connection.prepareStatement(sqlInsert1);

    System.out.println(connection.getAutoCommit());

    psInsert.execute();
    psInsert.close();

}

當您執行INSERT命令時,它會將指定的行插入到表中。 此行僅對執行此操作的事務可見,而對其他事務不可見(如果它們使用默認的“已提交”隔離級別)。 在隱式(由於自動提交)或顯式手動提交之后,插入的行對所有事務都是可見的。 如果您回滾事務而不是提交,則該行將消失。

其他數據修改操作以相同的方式工作。 未提交的更改僅對執行它們的事務可見,已提交的更改對所有人可見。

事務有不同的隔離級別,但是 H2 的默認存儲引擎在 1.4.199 中還不支持它們(這種支持將在 1.4.200 中包含)。

每個 JDBC 連接都有自己的 session 並且這個 session 有自己的事務。 我猜你使用相同的連接來讀取插入的數據,因此它可以看到未提交的行。 如果您不想看到它們,請使用其他連接。

H2 中的數據定義命令(如CREATE TABLE )通常會導致隱式提交,詳見 H2 的文檔。

我添加了兩個連接,然后更改了隔離級別,我的問題是為什么第二個事務看不到第一個事務所做的更改。 第一個事務不提交更改,因此如果事務隔離級別為 TRANSACTION_READ_UNCOMMITTED,則第二個事務應該看到第一個事務的更改。

我知道:

H2 只支持三個隔離級別; 讀取未提交,讀取已提交和可序列化,只能在連接級別(不是每個事務)設置。 默認為已提交讀。

public class StartUseCases {

    private static Connection connection;

    private static Connection connection2;

    public StartUseCases() {
        try {

            connection = ConnectionManager.getConnectionManager();
            connection.setAutoCommit(false);
            connection.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);

            connection2 = ConnectionManager.getConnectionManager();
            connection2.setAutoCommit(false);
            connection2.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);

            InitDatabaseManager.initStarterTable(connection);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws SQLException {

        // init tables
        new StartUseCases();

        CRUD.getAllUsers(connection);
        CRUD.insertUsers(connection2);
        CRUD.getAllUsers(connection);
    }

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM