forked from plusone/simple-jdbc
refactor: 提取 TransactionTemplate,分离事务管理职责
将 executeTransaction / commitIfTrue 及 TransactionJdbcExecutor 从 SimpleJdbcTemplate 移至独立的 TransactionTemplate 类: - 新增 TransactionTemplate,封装事务生命周期(开启/提交/回滚) - SimpleJdbcTemplate 新增 transaction() 入口 - 更新 TransactionTest 适配新 API:template.transaction().execute() - 更新 README.md 事务章节,说明 TransactionTemplate 使用方式
This commit is contained in:
@@ -68,7 +68,9 @@ Maven 依赖:
|
||||
|
||||
## 4. 事务
|
||||
|
||||
- **`executeTransaction(consumer)`**:执行事务。传入 `ThrowingConsumer<JdbcOperations>`,若内部无异常则提交,有异常则回滚。
|
||||
通过 `TransactionTemplate` 管理事务,可直接创建或通过 `SimpleJdbcTemplate.transaction()` 获取。
|
||||
|
||||
- **`execute(consumer)`**:执行事务。传入 `ThrowingConsumer<JdbcOperations>`,若内部无异常则提交,有异常则回滚。
|
||||
- **`commitIfTrue(predicate)`**:执行事务。传入 `ThrowingPredicate<JdbcOperations>`,返回 `true` 提交,返回 `false` 或抛异常则回滚。
|
||||
|
||||
## 5. 参数构建
|
||||
@@ -246,7 +248,7 @@ if (result.getStatus() == BatchUpdateStatus.COMPLETED_WITH_ERRORS) {
|
||||
### 6.4 事务
|
||||
|
||||
```java
|
||||
jdbcTemplate.executeTransaction(jdbc -> {
|
||||
jdbcTemplate.transaction().execute(jdbc -> {
|
||||
...
|
||||
jdbc.update(...);
|
||||
...
|
||||
@@ -255,7 +257,7 @@ jdbcTemplate.executeTransaction(jdbc -> {
|
||||
// 无异常则自动提交
|
||||
});
|
||||
|
||||
jdbcTemplate.commitIfTrue(jdbc -> {
|
||||
jdbcTemplate.transaction().commitIfTrue(jdbc -> {
|
||||
...
|
||||
jdbc.update(...);
|
||||
...
|
||||
|
||||
@@ -26,8 +26,6 @@ import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import xyz.zhouxy.plusone.commons.function.ThrowingConsumer;
|
||||
import xyz.zhouxy.plusone.commons.function.ThrowingPredicate;
|
||||
import xyz.zhouxy.plusone.commons.util.AssertTools;
|
||||
|
||||
/**
|
||||
@@ -35,19 +33,23 @@ import xyz.zhouxy.plusone.commons.util.AssertTools;
|
||||
*
|
||||
* <p>
|
||||
* 对 JDBC 的简单封装,方便数据库操作,支持事务,支持批量操作,支持自定义结果集映射
|
||||
* </p>
|
||||
*
|
||||
* @author ZhouXY
|
||||
* @since 1.0.0
|
||||
* @see TransactionTemplate
|
||||
*/
|
||||
public class SimpleJdbcTemplate implements JdbcOperations {
|
||||
|
||||
@Nonnull
|
||||
private final DataSource dataSource;
|
||||
|
||||
@Nonnull
|
||||
private final TransactionTemplate transactionTemplate;
|
||||
|
||||
public SimpleJdbcTemplate(@Nonnull DataSource dataSource) {
|
||||
AssertTools.checkNotNull(dataSource);
|
||||
this.dataSource = dataSource;
|
||||
this.transactionTemplate = new TransactionTemplate(dataSource);
|
||||
}
|
||||
|
||||
// #region - query
|
||||
@@ -184,203 +186,10 @@ public class SimpleJdbcTemplate implements JdbcOperations {
|
||||
|
||||
// #region - transaction
|
||||
|
||||
/**
|
||||
* 执行事务。如果未发生异常,则提交事务;当有异常发生时,回滚事务
|
||||
*
|
||||
* <p>
|
||||
* operations 中使用 JdbcExecutor 实参进行 JDBC 操作,这些操作在一个连接中
|
||||
* </p>
|
||||
*
|
||||
* @param <E> 异常类型
|
||||
* @param operations 事务操作
|
||||
* @throws SQLException SQL 异常
|
||||
* @throws TransactionException 事务异常。事务中的异常会包装在该异常中。
|
||||
*/
|
||||
public <E extends Exception> void executeTransaction(
|
||||
@Nonnull final ThrowingConsumer<JdbcOperations, E> operations)
|
||||
throws TransactionException, SQLException {
|
||||
AssertTools.checkNotNull(operations, "Operations can not be null.");
|
||||
try (Connection conn = this.dataSource.getConnection()) {
|
||||
final boolean autoCommit = conn.getAutoCommit();
|
||||
try {
|
||||
conn.setAutoCommit(false);
|
||||
operations.accept(new TransactionJdbcExecutor(conn));
|
||||
conn.commit();
|
||||
}
|
||||
catch (Exception e) {
|
||||
try {
|
||||
conn.rollback();
|
||||
}
|
||||
catch (SQLException ex) {
|
||||
e.addSuppressed(ex);
|
||||
}
|
||||
throw new TransactionException(e);
|
||||
}
|
||||
finally {
|
||||
conn.setAutoCommit(autoCommit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行事务。
|
||||
* 如果 {@code operations} 返回 {@code true},则提交事务;
|
||||
* 如果抛出异常,或返回 {@code false},则回滚事务
|
||||
*
|
||||
* @param <E> 事务中的异常
|
||||
* @param operations 事务操作
|
||||
* @throws SQLException 数据库异常
|
||||
* @throws TransactionException 事务异常。事务中的异常会包装在该异常中。
|
||||
*/
|
||||
public <E extends Exception> void commitIfTrue(
|
||||
@Nonnull final ThrowingPredicate<JdbcOperations, E> operations)
|
||||
throws SQLException, TransactionException {
|
||||
AssertTools.checkNotNull(operations, "Operations can not be null.");
|
||||
try (Connection conn = this.dataSource.getConnection()) {
|
||||
final boolean autoCommit = conn.getAutoCommit();
|
||||
try {
|
||||
conn.setAutoCommit(false);
|
||||
if (operations.test(new TransactionJdbcExecutor(conn))) {
|
||||
conn.commit();
|
||||
}
|
||||
else {
|
||||
conn.rollback();
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
try {
|
||||
conn.rollback();
|
||||
}
|
||||
catch (SQLException ex) {
|
||||
e.addSuppressed(ex);
|
||||
}
|
||||
throw new TransactionException(e);
|
||||
}
|
||||
finally {
|
||||
conn.setAutoCommit(autoCommit);
|
||||
}
|
||||
}
|
||||
public TransactionTemplate transaction() {
|
||||
return this.transactionTemplate;
|
||||
}
|
||||
|
||||
// #endregion
|
||||
|
||||
private static final class TransactionJdbcExecutor implements JdbcOperations {
|
||||
|
||||
private final Connection conn;
|
||||
|
||||
private TransactionJdbcExecutor(Connection conn) {
|
||||
this.conn = conn;
|
||||
}
|
||||
|
||||
// #region - query
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T> T query(String sql, Object[] params, ResultHandler<T> resultHandler)
|
||||
throws SQLException {
|
||||
return JdbcOperationSupport.query(this.conn, sql, params, resultHandler);
|
||||
}
|
||||
|
||||
// #endregion
|
||||
|
||||
// #region - queryList
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T> List<T> queryList(String sql, Object[] params, RowMapper<T> rowMapper)
|
||||
throws SQLException {
|
||||
return JdbcOperationSupport.queryList(this.conn, sql, params, rowMapper);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T> List<T> queryList(String sql, Object[] params, Class<T> clazz)
|
||||
throws SQLException {
|
||||
return JdbcOperationSupport.queryList(this.conn, sql, params, clazz);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public List<Map<String, Object>> queryList(String sql, Object[] params)
|
||||
throws SQLException {
|
||||
return JdbcOperationSupport.queryList(this.conn, sql, params, RowMapper.HASH_MAP_MAPPER);
|
||||
}
|
||||
|
||||
// #endregion
|
||||
|
||||
// #region - queryFirst
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T> Optional<T> queryFirst(String sql, Object[] params, RowMapper<T> rowMapper)
|
||||
throws SQLException {
|
||||
final T result = JdbcOperationSupport.queryFirst(this.conn, sql, params, rowMapper);
|
||||
return Optional.ofNullable(result);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T> Optional<T> queryFirst(String sql, Object[] params, Class<T> clazz)
|
||||
throws SQLException {
|
||||
final T result = JdbcOperationSupport.queryFirst(this.conn, sql, params, clazz);
|
||||
return Optional.ofNullable(result);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public Optional<Map<String, Object>> queryFirst(String sql, Object[] params)
|
||||
throws SQLException {
|
||||
final Map<String, Object> result = JdbcOperationSupport
|
||||
.queryFirst(this.conn, sql, params, RowMapper.HASH_MAP_MAPPER);
|
||||
return Optional.ofNullable(result);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean queryBoolean(String sql, Object[] params)
|
||||
throws SQLException {
|
||||
final Boolean result = JdbcOperationSupport
|
||||
.queryFirst(this.conn, sql, params, Boolean.class);
|
||||
return Boolean.TRUE.equals(result);
|
||||
}
|
||||
|
||||
// #endregion
|
||||
|
||||
// #region - update & batchUpdate
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int update(String sql, Object[] params)
|
||||
throws SQLException {
|
||||
return JdbcOperationSupport.update(this.conn, sql, params);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T> List<T> updateAndReturnKeys(String sql, Object[] params, RowMapper<T> rowMapper)
|
||||
throws SQLException {
|
||||
return JdbcOperationSupport.updateAndReturnKeys(this.conn, sql, params, rowMapper);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public BatchUpdateResult batchUpdate(String sql, @Nullable Collection<Object[]> params, int batchSize)
|
||||
throws SQLException {
|
||||
return JdbcOperationSupport.batchUpdate(this.conn, sql, params, batchSize, false);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public BatchUpdateResult batchUpdate(String sql,
|
||||
@Nullable Collection<Object[]> params,
|
||||
int batchSize,
|
||||
boolean quietly) throws SQLException {
|
||||
return JdbcOperationSupport
|
||||
.batchUpdate(this.conn, sql, params, batchSize, quietly);
|
||||
}
|
||||
|
||||
// #endregion
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
271
src/main/java/xyz/zhouxy/jdbc/TransactionTemplate.java
Normal file
271
src/main/java/xyz/zhouxy/jdbc/TransactionTemplate.java
Normal file
@@ -0,0 +1,271 @@
|
||||
/*
|
||||
* Copyright 2026-present ZhouXY
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package xyz.zhouxy.jdbc;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import xyz.zhouxy.plusone.commons.function.ThrowingConsumer;
|
||||
import xyz.zhouxy.plusone.commons.function.ThrowingPredicate;
|
||||
import xyz.zhouxy.plusone.commons.util.AssertTools;
|
||||
|
||||
/**
|
||||
* 事务模板,提供事务执行能力。
|
||||
*
|
||||
* <p>
|
||||
* 负责管理事务的生命周期:开启、提交、回滚、恢复自动提交。
|
||||
* 事务内的 JDBC 操作通过 {@link JdbcOperations} 接口进行,
|
||||
* 所有操作共享同一个数据库连接。
|
||||
* </p>
|
||||
*
|
||||
* <p>使用示例:</p>
|
||||
* <pre>{@code
|
||||
* TransactionTemplate tx = new TransactionTemplate(dataSource);
|
||||
*
|
||||
* // 消费者模式:无异常自动提交
|
||||
* tx.execute(ops -> {
|
||||
* ops.update("INSERT INTO ...", buildParams(...));
|
||||
* ops.update("UPDATE ...", buildParams(...));
|
||||
* });
|
||||
*
|
||||
* // 谓词模式:返回 true 提交,false 回滚
|
||||
* tx.commitIfTrue(ops -> {
|
||||
* ops.update("UPDATE ...", buildParams(...));
|
||||
* return ops.queryBoolean("SELECT ...", buildParams(...));
|
||||
* });
|
||||
* }</pre>
|
||||
*
|
||||
* @author ZhouXY
|
||||
* @since 1.1.0
|
||||
*/
|
||||
public class TransactionTemplate {
|
||||
|
||||
@Nonnull
|
||||
private final DataSource dataSource;
|
||||
|
||||
public TransactionTemplate(@Nonnull DataSource dataSource) {
|
||||
AssertTools.checkNotNull(dataSource);
|
||||
this.dataSource = dataSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行事务。如果未发生异常,则提交事务;当有异常发生时,回滚事务
|
||||
*
|
||||
* <p>
|
||||
* operations 中使用 JdbcExecutor 实参进行 JDBC 操作,这些操作在一个连接中
|
||||
* </p>
|
||||
*
|
||||
* @param <E> 异常类型
|
||||
* @param operations 事务操作
|
||||
* @throws SQLException SQL 异常
|
||||
* @throws TransactionException 事务异常。事务中的异常会包装在该异常中。
|
||||
*/
|
||||
public <E extends Exception> void execute(
|
||||
@Nonnull final ThrowingConsumer<JdbcOperations, E> operations)
|
||||
throws TransactionException, SQLException {
|
||||
AssertTools.checkNotNull(operations, "Operations can not be null.");
|
||||
try (Connection conn = this.dataSource.getConnection()) {
|
||||
final boolean autoCommit = conn.getAutoCommit();
|
||||
try {
|
||||
conn.setAutoCommit(false);
|
||||
operations.accept(new TransactionJdbcExecutor(conn));
|
||||
conn.commit();
|
||||
}
|
||||
catch (Exception e) {
|
||||
rollbackSilently(conn, e);
|
||||
throw new TransactionException(e);
|
||||
}
|
||||
finally {
|
||||
conn.setAutoCommit(autoCommit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行事务。
|
||||
* 如果 {@code operations} 返回 {@code true},则提交事务;
|
||||
* 如果抛出异常,或返回 {@code false},则回滚事务
|
||||
*
|
||||
* @param <E> 事务中的异常
|
||||
* @param operations 事务操作
|
||||
* @throws SQLException 数据库异常
|
||||
* @throws TransactionException 事务异常。事务中的异常会包装在该异常中。
|
||||
*/
|
||||
public <E extends Exception> void commitIfTrue(
|
||||
@Nonnull final ThrowingPredicate<JdbcOperations, E> operations)
|
||||
throws SQLException, TransactionException {
|
||||
AssertTools.checkNotNull(operations, "Operations can not be null.");
|
||||
try (Connection conn = this.dataSource.getConnection()) {
|
||||
final boolean autoCommit = conn.getAutoCommit();
|
||||
try {
|
||||
conn.setAutoCommit(false);
|
||||
if (operations.test(new TransactionJdbcExecutor(conn))) {
|
||||
conn.commit();
|
||||
}
|
||||
else {
|
||||
conn.rollback();
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
rollbackSilently(conn, e);
|
||||
throw new TransactionException(e);
|
||||
}
|
||||
finally {
|
||||
conn.setAutoCommit(autoCommit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void rollbackSilently(Connection conn, Exception e) {
|
||||
try {
|
||||
conn.rollback();
|
||||
}
|
||||
catch (SQLException ex) {
|
||||
e.addSuppressed(ex);
|
||||
}
|
||||
}
|
||||
|
||||
// #region - TransactionJdbcExecutor
|
||||
|
||||
private static final class TransactionJdbcExecutor implements JdbcOperations {
|
||||
|
||||
private final Connection conn;
|
||||
|
||||
private TransactionJdbcExecutor(Connection conn) {
|
||||
this.conn = conn;
|
||||
}
|
||||
|
||||
// #region - query
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T> T query(String sql, Object[] params, ResultHandler<T> resultHandler)
|
||||
throws SQLException {
|
||||
return JdbcOperationSupport.query(this.conn, sql, params, resultHandler);
|
||||
}
|
||||
|
||||
// #endregion
|
||||
|
||||
// #region - queryList
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T> List<T> queryList(String sql, Object[] params, RowMapper<T> rowMapper)
|
||||
throws SQLException {
|
||||
return JdbcOperationSupport.queryList(this.conn, sql, params, rowMapper);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T> List<T> queryList(String sql, Object[] params, Class<T> clazz)
|
||||
throws SQLException {
|
||||
return JdbcOperationSupport.queryList(this.conn, sql, params, clazz);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public List<Map<String, Object>> queryList(String sql, Object[] params)
|
||||
throws SQLException {
|
||||
return JdbcOperationSupport.queryList(this.conn, sql, params, RowMapper.HASH_MAP_MAPPER);
|
||||
}
|
||||
|
||||
// #endregion
|
||||
|
||||
// #region - queryFirst
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T> Optional<T> queryFirst(String sql, Object[] params, RowMapper<T> rowMapper)
|
||||
throws SQLException {
|
||||
final T result = JdbcOperationSupport.queryFirst(this.conn, sql, params, rowMapper);
|
||||
return Optional.ofNullable(result);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T> Optional<T> queryFirst(String sql, Object[] params, Class<T> clazz)
|
||||
throws SQLException {
|
||||
final T result = JdbcOperationSupport.queryFirst(this.conn, sql, params, clazz);
|
||||
return Optional.ofNullable(result);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public Optional<Map<String, Object>> queryFirst(String sql, Object[] params)
|
||||
throws SQLException {
|
||||
final Map<String, Object> result = JdbcOperationSupport
|
||||
.queryFirst(this.conn, sql, params, RowMapper.HASH_MAP_MAPPER);
|
||||
return Optional.ofNullable(result);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean queryBoolean(String sql, Object[] params)
|
||||
throws SQLException {
|
||||
final Boolean result = JdbcOperationSupport
|
||||
.queryFirst(this.conn, sql, params, Boolean.class);
|
||||
return Boolean.TRUE.equals(result);
|
||||
}
|
||||
|
||||
// #endregion
|
||||
|
||||
// #region - update & batchUpdate
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int update(String sql, Object[] params)
|
||||
throws SQLException {
|
||||
return JdbcOperationSupport.update(this.conn, sql, params);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T> List<T> updateAndReturnKeys(String sql, Object[] params, RowMapper<T> rowMapper)
|
||||
throws SQLException {
|
||||
return JdbcOperationSupport.updateAndReturnKeys(this.conn, sql, params, rowMapper);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public BatchUpdateResult batchUpdate(String sql, @Nullable Collection<Object[]> params, int batchSize)
|
||||
throws SQLException {
|
||||
return JdbcOperationSupport.batchUpdate(this.conn, sql, params, batchSize, false);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public BatchUpdateResult batchUpdate(String sql,
|
||||
@Nullable Collection<Object[]> params,
|
||||
int batchSize,
|
||||
boolean quietly) throws SQLException {
|
||||
return JdbcOperationSupport
|
||||
.batchUpdate(this.conn, sql, params, batchSize, quietly);
|
||||
}
|
||||
|
||||
// #endregion
|
||||
|
||||
}
|
||||
|
||||
// #endregion
|
||||
}
|
||||
@@ -16,9 +16,10 @@ import xyz.zhouxy.jdbc.SimpleJdbcTemplate;
|
||||
import xyz.zhouxy.jdbc.TransactionException;
|
||||
|
||||
/**
|
||||
* 事务 API 测试:executeTransaction、commitIfTrue。
|
||||
* 事务 API 测试:通过 {@link xyz.zhouxy.jdbc.TransactionTemplate#execute} 和
|
||||
* {@link xyz.zhouxy.jdbc.TransactionTemplate#commitIfTrue} 测试事务提交与回滚。
|
||||
*/
|
||||
@DisplayName("SimpleJdbcTemplate 事务操作")
|
||||
@DisplayName("TransactionTemplate 事务操作")
|
||||
class TransactionTest extends BaseH2Test {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(TransactionTest.class);
|
||||
@@ -28,14 +29,14 @@ class TransactionTest extends BaseH2Test {
|
||||
resetDatabase();
|
||||
}
|
||||
|
||||
// ==================== executeTransaction 正常提交 ====================
|
||||
// ==================== execute 正常提交 ====================
|
||||
|
||||
@Test
|
||||
@DisplayName("executeTransaction:正常提交,数据持久化")
|
||||
@DisplayName("execute:正常提交,数据持久化")
|
||||
void testExecuteTransactionCommit() throws Exception {
|
||||
SimpleJdbcTemplate template = createTemplate();
|
||||
|
||||
template.executeTransaction((JdbcOperations ops) -> {
|
||||
template.transaction().execute((JdbcOperations ops) -> {
|
||||
ops.update("INSERT INTO users (username, email, age, balance, active) VALUES (?, ?, ?, ?, ?)",
|
||||
buildParams("txUser1", "tx1@test.com", 25, 1000L, true));
|
||||
ops.update("UPDATE users SET balance = ? WHERE username = ?",
|
||||
@@ -56,10 +57,10 @@ class TransactionTest extends BaseH2Test {
|
||||
logger.info("事务提交验证通过");
|
||||
}
|
||||
|
||||
// ==================== executeTransaction 异常回滚 ====================
|
||||
// ==================== execute 异常回滚 ====================
|
||||
|
||||
@Test
|
||||
@DisplayName("executeTransaction:异常回滚,数据恢复原状")
|
||||
@DisplayName("execute:异常回滚,数据恢复原状")
|
||||
void testExecuteTransactionRollback() throws Exception {
|
||||
SimpleJdbcTemplate template = createTemplate();
|
||||
|
||||
@@ -69,7 +70,7 @@ class TransactionTest extends BaseH2Test {
|
||||
buildParams("alice"), Long.class);
|
||||
|
||||
TransactionException ex = assertThrows(TransactionException.class, () ->
|
||||
template.executeTransaction((JdbcOperations ops) -> {
|
||||
template.transaction().execute((JdbcOperations ops) -> {
|
||||
ops.update("UPDATE users SET balance = ? WHERE username = ?",
|
||||
buildParams(0L, "alice"));
|
||||
ops.update("INSERT INTO users (username, email) VALUES (?, ?)",
|
||||
@@ -99,12 +100,12 @@ class TransactionTest extends BaseH2Test {
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("executeTransaction:SQL 异常触发回滚")
|
||||
@DisplayName("execute:SQL 异常触发回滚")
|
||||
void testExecuteTransactionSqlExceptionRollback() {
|
||||
SimpleJdbcTemplate template = createTemplate();
|
||||
|
||||
assertThrows(TransactionException.class, () ->
|
||||
template.executeTransaction((JdbcOperations ops) -> {
|
||||
template.transaction().execute((JdbcOperations ops) -> {
|
||||
ops.update("INSERT INTO users (username) VALUES (?)",
|
||||
buildParams("validUser"));
|
||||
// 错误的 SQL
|
||||
@@ -120,14 +121,14 @@ class TransactionTest extends BaseH2Test {
|
||||
});
|
||||
}
|
||||
|
||||
// ==================== commitIfTrue 返回 true 提交 ====================
|
||||
// ==================== commitIfTrue:返回 true 提交 ====================
|
||||
|
||||
@Test
|
||||
@DisplayName("commitIfTrue:返回 true 提交事务")
|
||||
void testCommitIfTrueCommit() throws Exception {
|
||||
SimpleJdbcTemplate template = createTemplate();
|
||||
|
||||
template.commitIfTrue((JdbcOperations ops) -> {
|
||||
template.transaction().commitIfTrue((JdbcOperations ops) -> {
|
||||
ops.update("INSERT INTO users (username, email) VALUES (?, ?)",
|
||||
buildParams("cftUser", "cft@test.com"));
|
||||
return true;
|
||||
@@ -147,7 +148,7 @@ class TransactionTest extends BaseH2Test {
|
||||
void testCommitIfFalseRollback() throws Exception {
|
||||
SimpleJdbcTemplate template = createTemplate();
|
||||
|
||||
template.commitIfTrue((JdbcOperations ops) -> {
|
||||
template.transaction().commitIfTrue((JdbcOperations ops) -> {
|
||||
ops.update("INSERT INTO users (username, email) VALUES (?, ?)",
|
||||
buildParams("cffUser", "cff@test.com"));
|
||||
return false;
|
||||
@@ -168,7 +169,7 @@ class TransactionTest extends BaseH2Test {
|
||||
SimpleJdbcTemplate template = createTemplate();
|
||||
|
||||
assertThrows(TransactionException.class, () ->
|
||||
template.commitIfTrue((JdbcOperations ops) -> {
|
||||
template.transaction().commitIfTrue((JdbcOperations ops) -> {
|
||||
ops.update("INSERT INTO users (username) VALUES (?)",
|
||||
buildParams("exUser"));
|
||||
throw new IllegalStateException("条件不满足");
|
||||
@@ -186,11 +187,11 @@ class TransactionTest extends BaseH2Test {
|
||||
// ==================== 事务内查询可见性 ====================
|
||||
|
||||
@Test
|
||||
@DisplayName("executeTransaction:事务内可查询到未提交的数据")
|
||||
@DisplayName("execute:事务内可查询到未提交的数据")
|
||||
void testTransactionVisibility() throws Exception {
|
||||
SimpleJdbcTemplate template = createTemplate();
|
||||
|
||||
template.executeTransaction((JdbcOperations ops) -> {
|
||||
template.transaction().execute((JdbcOperations ops) -> {
|
||||
ops.update("INSERT INTO users (username, email) VALUES (?, ?)",
|
||||
buildParams("visible", "visible@test.com"));
|
||||
|
||||
@@ -207,13 +208,13 @@ class TransactionTest extends BaseH2Test {
|
||||
// ==================== 边界情况 ====================
|
||||
|
||||
@Test
|
||||
@DisplayName("executeTransaction:空操作(无异常)正常提交")
|
||||
@DisplayName("execute:空操作(无异常)正常提交")
|
||||
void testExecuteTransactionEmpty() throws Exception {
|
||||
SimpleJdbcTemplate template = createTemplate();
|
||||
|
||||
// 空操作不应抛异常
|
||||
assertDoesNotThrow(() ->
|
||||
template.executeTransaction(ops -> { /* no-op */ }));
|
||||
template.transaction().execute(ops -> { /* no-op */ }));
|
||||
|
||||
// 数据应保持不变
|
||||
int count = template.query("SELECT COUNT(*) FROM users",
|
||||
@@ -222,12 +223,12 @@ class TransactionTest extends BaseH2Test {
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("executeTransaction:null 操作抛异常")
|
||||
@DisplayName("execute:null 操作抛异常")
|
||||
@SuppressWarnings("null")
|
||||
void testExecuteTransactionNullOps() {
|
||||
SimpleJdbcTemplate template = createTemplate();
|
||||
|
||||
assertThrows(Exception.class, () ->
|
||||
template.executeTransaction(null));
|
||||
template.transaction().execute(null));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user