From c1f12172e2716baa6ee01c831994ab7cb03eca7d Mon Sep 17 00:00:00 2001 From: "Z.P" <74527377+ZPZP1@users.noreply.github.com> Date: Wed, 17 Jan 2024 10:23:25 +0800 Subject: [PATCH] =?UTF-8?q?fix:=E4=BA=8B=E5=8A=A1=E5=90=8E=E7=BD=AE?= =?UTF-8?q?=E5=9B=9E=E8=B0=83=E4=B8=AD=E5=BC=80=E5=90=AF=E4=BA=8B=E5=8A=A1?= =?UTF-8?q?=E6=AD=BB=E5=BE=AA=E7=8E=AF=20(#621)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: zhangpeng --- .../fixture/v1/DsTransactionalTest.java | 22 ----------- .../fixture/v1/service/tx/OrderService.java | 25 ++++++++++++ .../fixture/v3/DsTransactionalTest.java | 22 ----------- .../fixture/v3/service/tx/OrderService.java | 25 ++++++++++++ .../datasource/tx/TransactionContext.java | 3 ++ .../datasource/tx/TransactionalTemplate.java | 39 +++++++------------ 6 files changed, 68 insertions(+), 68 deletions(-) diff --git a/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/v1/DsTransactionalTest.java b/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/v1/DsTransactionalTest.java index b932b403..3e6d222b 100644 --- a/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/v1/DsTransactionalTest.java +++ b/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/v1/DsTransactionalTest.java @@ -61,14 +61,6 @@ public void testDsTransactional() { PlaceOrderRequest placeOrderRequest = new PlaceOrderRequest(1, 1, 22, OrderStatus.INIT); //商品不足 - TransactionContext.registerSynchronization(new TransactionSynchronization() { - @Override - public void afterCompletion(int status) { - if (status == STATUS_ROLLED_BACK) { - placeOrderRequest.setOrderStatus(OrderStatus.FAIL); - } - } - }); assertThrows(RuntimeException.class, () -> orderService.placeOrder(placeOrderRequest)); assertThat(placeOrderRequest.getOrderStatus()).isEqualTo(OrderStatus.FAIL); assertThat(orderService.selectOrders()).isEmpty(); @@ -76,14 +68,6 @@ public void afterCompletion(int status) { assertThat(productService.selectProduct()).isEqualTo(new Product(1, 10.0, 20)); //账户不足 - TransactionContext.registerSynchronization(new TransactionSynchronization() { - @Override - public void afterCompletion(int status) { - if (status == STATUS_ROLLED_BACK) { - placeOrderRequest.setOrderStatus(OrderStatus.FAIL); - } - } - }); placeOrderRequest.setAmount(6); placeOrderRequest.setOrderStatus(OrderStatus.INIT); assertThrows(RuntimeException.class, () -> orderService.placeOrder(placeOrderRequest)); @@ -93,12 +77,6 @@ public void afterCompletion(int status) { assertThat(productService.selectProduct()).isEqualTo(new Product(1, 10.0, 20)); //正常下单 - TransactionContext.registerSynchronization(new TransactionSynchronization() { - @Override - public void afterCommit() { - placeOrderRequest.setOrderStatus(OrderStatus.SUCCESS); - } - }); placeOrderRequest.setAmount(5); placeOrderRequest.setOrderStatus(OrderStatus.INIT); assertThat(orderService.placeOrder(placeOrderRequest)).isEqualTo(OrderStatus.INIT); diff --git a/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/v1/service/tx/OrderService.java b/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/v1/service/tx/OrderService.java index d6bacaec..4998555e 100644 --- a/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/v1/service/tx/OrderService.java +++ b/dynamic-datasource-spring-boot-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/v1/service/tx/OrderService.java @@ -17,7 +17,9 @@ import com.baomidou.dynamic.datasource.annotation.DS; import com.baomidou.dynamic.datasource.annotation.DSTransactional; +import com.baomidou.dynamic.datasource.tx.TransactionContext; import org.springframework.stereotype.Service; +import org.springframework.transaction.support.TransactionSynchronization; import javax.sql.DataSource; import java.sql.*; @@ -40,6 +42,29 @@ public OrderService(AccountService accountService, ProductService productService @DSTransactional public int placeOrder(PlaceOrderRequest request) { + TransactionContext.registerSynchronization(new TransactionSynchronization() { + @Override + public void afterCompletion(int status) { + if (status == STATUS_ROLLED_BACK) { + request.setOrderStatus(OrderStatus.FAIL); + } + } + }); + TransactionContext.registerSynchronization(new TransactionSynchronization() { + @Override + public void afterCompletion(int status) { + if (status == STATUS_ROLLED_BACK) { + request.setOrderStatus(OrderStatus.FAIL); + } + } + }); + TransactionContext.registerSynchronization(new TransactionSynchronization() { + @Override + public void afterCommit() { + request.setOrderStatus(OrderStatus.SUCCESS); + } + }); + try (Connection connection = dataSource.getConnection()) { Integer userId = request.getUserId(); Integer productId = request.getProductId(); diff --git a/dynamic-datasource-spring-boot3-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/v3/DsTransactionalTest.java b/dynamic-datasource-spring-boot3-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/v3/DsTransactionalTest.java index 91de3184..47bf3e49 100644 --- a/dynamic-datasource-spring-boot3-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/v3/DsTransactionalTest.java +++ b/dynamic-datasource-spring-boot3-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/v3/DsTransactionalTest.java @@ -61,14 +61,6 @@ public void testDsTransactional() { PlaceOrderRequest placeOrderRequest = new PlaceOrderRequest(1, 1, 22, OrderStatus.INIT); //商品不足 - TransactionContext.registerSynchronization(new TransactionSynchronization() { - @Override - public void afterCompletion(int status) { - if (status == STATUS_ROLLED_BACK) { - placeOrderRequest.setOrderStatus(OrderStatus.FAIL); - } - } - }); assertThrows(RuntimeException.class, () -> orderService.placeOrder(placeOrderRequest)); assertThat(placeOrderRequest.getOrderStatus()).isEqualTo(OrderStatus.FAIL); assertThat(orderService.selectOrders()).isEmpty(); @@ -76,14 +68,6 @@ public void afterCompletion(int status) { assertThat(productService.selectProduct()).isEqualTo(new Product(1, 10.0, 20)); //账户不足 - TransactionContext.registerSynchronization(new TransactionSynchronization() { - @Override - public void afterCompletion(int status) { - if (status == STATUS_ROLLED_BACK) { - placeOrderRequest.setOrderStatus(OrderStatus.FAIL); - } - } - }); placeOrderRequest.setAmount(6); placeOrderRequest.setOrderStatus(OrderStatus.INIT); assertThrows(RuntimeException.class, () -> orderService.placeOrder(placeOrderRequest)); @@ -93,12 +77,6 @@ public void afterCompletion(int status) { assertThat(productService.selectProduct()).isEqualTo(new Product(1, 10.0, 20)); //正常下单 - TransactionContext.registerSynchronization(new TransactionSynchronization() { - @Override - public void afterCommit() { - placeOrderRequest.setOrderStatus(OrderStatus.SUCCESS); - } - }); placeOrderRequest.setAmount(5); placeOrderRequest.setOrderStatus(OrderStatus.INIT); assertThat(orderService.placeOrder(placeOrderRequest)).isEqualTo(OrderStatus.INIT); diff --git a/dynamic-datasource-spring-boot3-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/v3/service/tx/OrderService.java b/dynamic-datasource-spring-boot3-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/v3/service/tx/OrderService.java index 8d46b4c9..75cc21ad 100644 --- a/dynamic-datasource-spring-boot3-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/v3/service/tx/OrderService.java +++ b/dynamic-datasource-spring-boot3-starter/src/test/java/com/baomidou/dynamic/datasource/fixture/v3/service/tx/OrderService.java @@ -17,7 +17,9 @@ import com.baomidou.dynamic.datasource.annotation.DS; import com.baomidou.dynamic.datasource.annotation.DSTransactional; +import com.baomidou.dynamic.datasource.tx.TransactionContext; import org.springframework.stereotype.Service; +import org.springframework.transaction.support.TransactionSynchronization; import javax.sql.DataSource; import java.sql.*; @@ -40,6 +42,29 @@ public OrderService(AccountService accountService, ProductService productService @DSTransactional public int placeOrder(PlaceOrderRequest request) { + TransactionContext.registerSynchronization(new TransactionSynchronization() { + @Override + public void afterCompletion(int status) { + if (status == STATUS_ROLLED_BACK) { + request.setOrderStatus(OrderStatus.FAIL); + } + } + }); + TransactionContext.registerSynchronization(new TransactionSynchronization() { + @Override + public void afterCompletion(int status) { + if (status == STATUS_ROLLED_BACK) { + request.setOrderStatus(OrderStatus.FAIL); + } + } + }); + TransactionContext.registerSynchronization(new TransactionSynchronization() { + @Override + public void afterCommit() { + request.setOrderStatus(OrderStatus.SUCCESS); + } + }); + try (Connection connection = dataSource.getConnection()) { Integer userId = request.getUserId(); Integer productId = request.getProductId(); diff --git a/dynamic-datasource-spring/src/main/java/com/baomidou/dynamic/datasource/tx/TransactionContext.java b/dynamic-datasource-spring/src/main/java/com/baomidou/dynamic/datasource/tx/TransactionContext.java index 500e5473..a04a17ab 100644 --- a/dynamic-datasource-spring/src/main/java/com/baomidou/dynamic/datasource/tx/TransactionContext.java +++ b/dynamic-datasource-spring/src/main/java/com/baomidou/dynamic/datasource/tx/TransactionContext.java @@ -81,6 +81,9 @@ public static void registerSynchronization(TransactionSynchronization synchroniz if (Objects.isNull(synchronization)) { throw new IllegalArgumentException("TransactionSynchronization must not be null"); } + if (DsStrUtils.isEmpty(TransactionContext.getXID())) { + throw new IllegalStateException("Transaction is not active"); + } Set synchs = SYNCHRONIZATION_HOLDER.get(); synchs.add(synchronization); } diff --git a/dynamic-datasource-spring/src/main/java/com/baomidou/dynamic/datasource/tx/TransactionalTemplate.java b/dynamic-datasource-spring/src/main/java/com/baomidou/dynamic/datasource/tx/TransactionalTemplate.java index f9815544..a0606231 100644 --- a/dynamic-datasource-spring/src/main/java/com/baomidou/dynamic/datasource/tx/TransactionalTemplate.java +++ b/dynamic-datasource-spring/src/main/java/com/baomidou/dynamic/datasource/tx/TransactionalTemplate.java @@ -113,21 +113,22 @@ private Object doExecute(TransactionalExecutor transactionalExecutor) throws Thr boolean state = true; Object o; String xid = LocalTxUtil.startTransaction(); + boolean shouldInvokeAction = TransactionContext.getSynchronizations().isEmpty(); try { o = transactionalExecutor.execute(); } catch (Exception e) { state = !isRollback(e, transactionInfo); throw e; } finally { - invokeBeforeCompletion(); + invokeBeforeCompletion(shouldInvokeAction); if (state) { - invokeBeforeCommit(); + invokeBeforeCommit(shouldInvokeAction); LocalTxUtil.commit(xid); - invokeAfterCommit(); - invokeAfterCompletion(TransactionSynchronization.STATUS_COMMITTED); + invokeAfterCommit(shouldInvokeAction); + invokeAfterCompletion(TransactionSynchronization.STATUS_COMMITTED, shouldInvokeAction); } else { LocalTxUtil.rollback(xid); - invokeAfterCompletion(TransactionSynchronization.STATUS_ROLLED_BACK); + invokeAfterCompletion(TransactionSynchronization.STATUS_ROLLED_BACK, shouldInvokeAction); } } return o; @@ -241,8 +242,8 @@ public boolean isNotEmpty(Object[] array) { /** * Invoke before commit. */ - public void invokeBeforeCommit() { - if (shouldInvokeAction()) { + public void invokeBeforeCommit(boolean shouldInvokeAction) { + if (shouldInvokeAction) { for (TransactionSynchronization synchronization : TransactionContext.getSynchronizations()) { synchronization.beforeCommit(false); } @@ -252,8 +253,8 @@ public void invokeBeforeCommit() { /** * Invoke before completion . */ - public void invokeBeforeCompletion() { - if (shouldInvokeAction()) { + public void invokeBeforeCompletion(boolean shouldInvokeAction) { + if (shouldInvokeAction) { for (TransactionSynchronization synchronization : TransactionContext.getSynchronizations()) { synchronization.beforeCompletion(); } @@ -263,8 +264,8 @@ public void invokeBeforeCompletion() { /** * Invoke after commit. */ - public void invokeAfterCommit() { - if (shouldInvokeAction()) { + public void invokeAfterCommit(boolean shouldInvokeAction) { + if (shouldInvokeAction) { for (TransactionSynchronization synchronization : TransactionContext.getSynchronizations()) { synchronization.afterCommit(); } @@ -274,22 +275,12 @@ public void invokeAfterCommit() { /** * Invoke after completion. */ - public void invokeAfterCompletion(int status) { - if (shouldInvokeAction()) { + public void invokeAfterCompletion(int status, boolean shouldInvokeAction) { + if (shouldInvokeAction) { for (TransactionSynchronization synchronization : TransactionContext.getSynchronizations()) { synchronization.afterCompletion(status); } + TransactionContext.removeSynchronizations(); } - TransactionContext.removeSynchronizations(); - } - - /** - * Should invoke action boolean. - * - * @return the boolean - */ - public boolean shouldInvokeAction() { - //If there is a savepoint, the action should not be executed - return !ConnectionFactory.hasSavepoint(TransactionContext.getXID()); } } \ No newline at end of file