即使自动提交为假,从连接创建新语句是不是会提交所有内容?

Posted

技术标签:

【中文标题】即使自动提交为假,从连接创建新语句是不是会提交所有内容?【英文标题】:Is creating a new statement from a connection commit everything even if auto commit is false?即使自动提交为假,从连接创建新语句是否会提交所有内容? 【发布时间】:2019-07-24 09:58:20 【问题描述】:

我有以下代码:

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.jarApp.java 在同一文件夹中。

【问题讨论】:

【参考方案1】:

如果一个连接在事务中执行插入、更新或删除操作,那么该同一连接的其他语句将能够看到这些更改,即使这些更改尚未提交,其他连接可以看到它们。

(其实正常情况下其他连接在提交之前是看不到变化的,但是隔离级别为READ_UNCOMMITTED的事务会允许其他连接在原连接执行提交或者回滚之前看到变化。)

【讨论】:

以上是关于即使自动提交为假,从连接创建新语句是不是会提交所有内容?的主要内容,如果未能解决你的问题,请参考以下文章

为啥即使我们尝试获取数据而不是更新/提交新数据,GraphQL 也会查询 POST 请求?

Java 是不是会检查“&&”(和)运算符中的所有参数,即使其中一个参数为假?

JDBC事务

JDBC事务

提交并自动添加所有未跟踪的文件

在 oracle 中执行存储过程后是不是发生任何自动提交?