首页 > 解决方案 > H2事务总是自动提交为什么?

问题描述

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

在 pom.xml 中,我依赖于 H2 数据库:

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

我以这种方式创建了一个连接,您可以看到我将 autocommit 设置为 false。我的 H2 数据库在内存中。

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();

}

标签: javatransactionsh2

解决方案


我添加了两个连接,然后更改了隔离级别,我的问题是为什么第二个事务看不到第一个事务所做的更改。第一个事务不提交更改,因此如果事务隔离级别为 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);
    }

}

推荐阅读