You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

同一事务内变更的可见性问题及JDBC与Spring场景差异

Understanding Transaction Visibility in JDBC & Spring

Great question—this is such a common gotcha when moving between raw JDBC and Spring's managed transactions. Let’s unpack what’s happening here, step by step.

Core Rule: Same Transaction = Changes Are Visible

First things first: Within a single transaction (same database connection), all your insert/update changes should be immediately visible to subsequent select statements in that same transaction. This is a fundamental part of ACID compliance—your transaction should see its own state consistently, regardless of isolation level (isolation levels only govern visibility between different concurrent transactions, not your own).

Why Raw JDBC Might Seem to "Hide" Changes

If you’re not seeing your uncommitted changes in raw JDBC, the most likely culprit is not using the same Connection object for all operations in the transaction. Transactions are strictly bound to a single Connection in JDBC. If your insert/update uses one connection, and your subsequent select grabs a new one from the pool, that new connection won’t see the uncommitted changes (since they’re tied to the original connection’s transaction).

Double-check your raw JDBC code—make sure you’re reusing the same Connection instance for every statement in the transaction. For example, this code will see the inserted data:

// Get a single connection for the entire transaction
Connection conn = DriverManager.getConnection(dbUrl, user, password);
conn.setAutoCommit(false);

try {
    // Insert data
    PreparedStatement insertStmt = conn.prepareStatement("INSERT INTO users(id, name) VALUES (?, ?)");
    insertStmt.setInt(1, 123);
    insertStmt.setString(2, "Alice");
    insertStmt.executeUpdate();

    // Select the same data using the SAME connection
    PreparedStatement selectStmt = conn.prepareStatement("SELECT name FROM users WHERE id = ?");
    selectStmt.setInt(1, 123);
    ResultSet rs = selectStmt.executeQuery();
    
    if (rs.next()) {
        System.out.println(rs.getString("name")); // Prints "Alice" immediately
    }

    conn.commit();
} catch (SQLException e) {
    conn.rollback();
} finally {
    conn.close();
}

If your code is creating a new Connection for the select, that’s why you’re not seeing the changes.

Why Spring JdbcTemplate Works As Expected

Spring’s DataSourceTransactionManager solves this problem automatically by binding the transactional Connection to the current thread (using a ThreadLocal). Every time you use JdbcTemplate within the transaction context, it retrieves the pre-bound connection instead of grabbing a new one from the pool. This ensures all operations in the transaction share the same connection, so your uncommitted changes are visible to subsequent selects.

Spring handles all the connection management behind the scenes, so you don’t have to manually track or reuse connections—this is one of the key benefits of using Spring’s transaction abstraction.

Vendor/Driver Dependencies?

The rule of same-connection transaction visibility is part of the JDBC spec’s implicit behavior, so it should hold across all compliant drivers and databases. For your setup (mysql-connector-java 8.0.11, JDBC 4.2, Java 8), MySQL’s driver fully adheres to this—there’s no special configuration that would break this behavior. The only edge cases would be if you’re using a database with non-standard transaction semantics, but MySQL isn’t one of them.

Quick Recap

  • Same connection = same transaction = changes are visible: This is the baseline rule.
  • Raw JDBC issue: Almost always a connection reuse problem.
  • Spring’s magic: Thread-bound connections ensure all transactional operations share the same session.

内容的提问来源于stack exchange,提问作者Andreas Gelever

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:27:28