我正在setAutoCommit(false)
模式下使用JDBC。
在同一个事务中,我执行多个语句进行插入,更新和选择。
问题是:如果这些更改在同一事务中可见,以便后续操作吗?有什么具体规则?它是特定于供应商的吗?它是特定于驱动程序的吗?或者其他什么?
我使用mysql-connector-java 8.0.11,JDBC 4.2,java 8,在我的情况下没有可见的变化,例如。
try (Connection conn = dataSource.getConnection()) {
conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
conn.setAutoCommit(false);
try (PreparedStatement statement = conn.prepareStatement(sqlInsert, PreparedStatement.RETURN_GENERATED_KEYS)) {
statement.setString(1, "testData");
statement.executeUpdate();
System.out.println("After insertion:");
// jdbc findAll impl.
findAll().forEach(System.out::println);
conn.commit();
} catch (SQLException ex) {
conn.rollback();
}
} catch (SQLException e) {
throw new RuntimeException();
}
此处,插入的未提交数据实际上在同一事务中不可见!
但是,如果我使用Spring的jdbcTemplate和Spring的DataSourceTransactionManager执行相同的操作,请执行以下操作:
final DefaultTransactionDefinition defaultTransactionDefinition = new DefaultTransactionDefinition();
defaultTransactionDefinition.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
TransactionStatus transaction = txManager.getTransaction(defaultTransactionDefinition);
try {
// jdbcTemplate insert impl.
insert("testData");
System.out.println("After insertion:");
// jdbcTemplate findAll impl.
findAll().forEach(System.out::println);
txManager.commit(transaction);
} catch (Exception e) {
txManager.rollback(transaction);
}
插入的未提交数据实际上在同一事务中可见!
我在JDBC规范中没有找到任何解释,并且与它混淆。
请解释一下这种行为。
P.S。我知道不同的隔离级别,但它们基本上适用于并发事务,而不是同一个事务。
答案 0 :(得分:2)
如果评论中的其他信息def replacestring(val):
reps = {'Parker':'Borker', '1St':'st', 'Sw':'SW', 'S W':'SW'}
for i,j in reps.items():
if i in val: val = val.replace(i,j)
return val
print(addr_df['ADDRESS1'].apply(replacestring))
创建了新连接,则问题是您使用一个连接+事务来更新数据,而另一个连接+事务用于选择数据。
选择查询受事务影响:事务确定可见或不可见。您具有事务1的连接1,其中您修改了数据(尚未提交),连接2与事务2执行选择。如果事务1尚未提交,则事务2无法查看事务1更改的数据。
如果使用findAll
和Spring事务管理器,事情会发生变化,因为Spring会做更多的工作来确保它为更新和选择使用相同的连接和事务。