├── src ├── test │ └── java │ │ └── com │ │ └── dtmcli │ │ └── java │ │ └── sample │ │ └── DtmcliJavaExamplesApplicationTests.java └── main │ ├── resources │ └── application.yml │ └── java │ └── com │ └── dtmcli │ └── java │ └── sample │ ├── DtmcliJavaSampleApplication.java │ ├── param │ └── TransReq.java │ ├── util │ └── DataSourceUtil.java │ └── controller │ ├── TransController.java │ ├── TccTestController.java │ └── TransBarrierController.java ├── README.md ├── .gitignore ├── LICENSE ├── pom.xml └── dtmcli-java-sample.iml /src/test/java/com/dtmcli/java/sample/DtmcliJavaExamplesApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.dtmcli.java.sample; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class DtmcliJavaExamplesApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } -------------------------------------------------------------------------------- /src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 8081 3 | 4 | dtm: 5 | ipPort: 'localhost:36789' 6 | 7 | spring: 8 | datasource: 9 | url: jdbc:mysql://localhost:3306/dtm_barrier?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC 10 | username: root 11 | password: 12345678 12 | driver-class-name: com.mysql.cj.jdbc.Driver 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### 快速开始 2 | 3 | #### 启动dtm 4 | 参考[dtm安装运行](https://dtm.pub/guide/install.html) 5 | 6 | #### 运行示例 7 | 运行服务 8 | 9 | ``` 10 | mvn package && java -jar target/dtmcli-java-sample-0.0.1-SNAPSHOT.jar 11 | ``` 12 | 13 | 触发成功的TCC事务 14 | ``` 15 | curl localhost:8081/tccBarrier 16 | ``` 17 | 18 | 触发回滚的TCC事务 19 | ``` 20 | curl localhost:8081/tccBarrierError 21 | ``` 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.nar 17 | *.ear 18 | *.zip 19 | *.tar.gz 20 | *.rar 21 | 22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 23 | hs_err_pid* 24 | .idea 25 | /target -------------------------------------------------------------------------------- /src/main/java/com/dtmcli/java/sample/DtmcliJavaSampleApplication.java: -------------------------------------------------------------------------------- 1 | package com.dtmcli.java.sample; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class DtmcliJavaSampleApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(DtmcliJavaSampleApplication.class, args); 11 | } 12 | 13 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 yedf 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/main/java/com/dtmcli/java/sample/param/TransReq.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Gypsophila open source organization. 3 | * 4 | * Licensed under the Apache License,Version2.0(the"License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.dtmcli.java.sample.param; 18 | 19 | import lombok.Data; 20 | 21 | /** 22 | * @author lixiaoshuang 23 | */ 24 | @Data 25 | public class TransReq { 26 | 27 | /** 28 | * 用户id 29 | */ 30 | private int userId; 31 | 32 | /** 33 | * 转入/转出金额 34 | */ 35 | private int amount; 36 | 37 | public TransReq(int userId, int amount) { 38 | this.userId = userId; 39 | this.amount = amount; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/com/dtmcli/java/sample/util/DataSourceUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Gypsophila open source organization. 3 | * 4 | * Licensed under the Apache License,Version2.0(the"License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.dtmcli.java.sample.util; 18 | 19 | import com.mysql.cj.jdbc.MysqlDataSource; 20 | import org.springframework.beans.factory.annotation.Value; 21 | import org.springframework.stereotype.Component; 22 | 23 | import java.sql.Connection; 24 | import java.sql.SQLException; 25 | 26 | /** 27 | * @author lixiaoshuang 28 | */ 29 | @Component 30 | public class DataSourceUtil { 31 | 32 | @Value("${spring.datasource.url}") 33 | private String url; 34 | 35 | @Value("${spring.datasource.username}") 36 | private String userName; 37 | 38 | @Value("${spring.datasource.password}") 39 | private String password; 40 | 41 | public Connection getConnecion() throws SQLException { 42 | MysqlDataSource mysqlDataSource = new MysqlDataSource(); 43 | mysqlDataSource.setUser(userName); 44 | mysqlDataSource.setURL(url); 45 | mysqlDataSource.setPassword(password); 46 | return mysqlDataSource.getConnection(); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/dtmcli/java/sample/controller/TransController.java: -------------------------------------------------------------------------------- 1 | package com.dtmcli.java.sample.controller; 2 | 3 | import common.constant.Constant; 4 | import common.model.TransResponse; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.RestController; 9 | 10 | 11 | @RestController 12 | @RequestMapping("api") 13 | public class TransController { 14 | 15 | Logger logger = LoggerFactory.getLogger(TransController.class); 16 | 17 | @RequestMapping("TransOutTry") 18 | public Object TransOutTry() { 19 | logger.info("TransOutTry"); 20 | return TransResponse.buildTransResponse(Constant.SUCCESS_RESULT); 21 | } 22 | 23 | @RequestMapping("TransOutConfirm") 24 | public Object TransOutConfirm() { 25 | logger.info("TransOutConfirm"); 26 | return TransResponse.buildTransResponse(Constant.SUCCESS_RESULT); 27 | 28 | } 29 | 30 | @RequestMapping("TransOutCancel") 31 | public Object TransOutCancel() { 32 | logger.info("TransOutCancel"); 33 | return TransResponse.buildTransResponse(Constant.SUCCESS_RESULT); 34 | 35 | } 36 | 37 | @RequestMapping("TransInTry") 38 | public Object TransInTry() { 39 | logger.info("TransInTry"); 40 | return TransResponse.buildTransResponse(Constant.SUCCESS_RESULT); 41 | 42 | } 43 | 44 | @RequestMapping("TransInConfirm") 45 | public Object TransInConfirm() { 46 | logger.info("TransInConfirm"); 47 | return TransResponse.buildTransResponse(Constant.SUCCESS_RESULT); 48 | } 49 | 50 | @RequestMapping("TransInCancel") 51 | public Object TransInCancel() { 52 | logger.info("TransInCancel"); 53 | return TransResponse.buildTransResponse(Constant.SUCCESS_RESULT); 54 | } 55 | } -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | 7 | org.springframework.boot 8 | spring-boot-starter-parent 9 | 2.5.4 10 | 11 | 12 | 13 | com.github.viticis 14 | dtmcli-java-sample 15 | 0.0.1-SNAPSHOT 16 | dtmcli-java-sample 17 | dtmcli-java-sample 18 | 19 | 20 | 1.8 21 | v1.5.4 22 | 23 | 24 | 25 | 26 | org.springframework.boot 27 | spring-boot-starter-web 28 | 29 | 30 | mysql 31 | mysql-connector-java 32 | 33 | 34 | org.springframework.boot 35 | spring-boot-devtools 36 | runtime 37 | true 38 | 39 | 40 | org.springframework.boot 41 | spring-boot-starter-test 42 | test 43 | 44 | 45 | com.github.yedf 46 | dtmcli-java 47 | v1.5.4 48 | 49 | 50 | 51 | 52 | 53 | jitpack.io 54 | https://jitpack.io 55 | 56 | 57 | 58 | 59 | 60 | 61 | org.springframework.boot 62 | spring-boot-maven-plugin 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /src/main/java/com/dtmcli/java/sample/controller/TccTestController.java: -------------------------------------------------------------------------------- 1 | package com.dtmcli.java.sample.controller; 2 | 3 | import client.DtmClient; 4 | import com.dtmcli.java.sample.param.TransReq; 5 | import lombok.extern.slf4j.Slf4j; 6 | import okhttp3.Response; 7 | import org.springframework.beans.factory.annotation.Value; 8 | import org.springframework.web.bind.annotation.RequestMapping; 9 | import org.springframework.web.bind.annotation.RestController; 10 | import tcc.Tcc; 11 | 12 | 13 | @RestController 14 | @RequestMapping(("api")) 15 | @Slf4j 16 | public class TccTestController { 17 | 18 | private static final String svc = "http://localhost:8081/api"; 19 | 20 | @Value("${dtm.ipPort}") 21 | private String ipPort; 22 | 23 | /** 24 | * 常规tcc demo 25 | * 26 | * @return 27 | */ 28 | @RequestMapping("testTcc") 29 | public String testTcc() { 30 | //创建dtm clinet 31 | DtmClient dtmClient = new DtmClient(ipPort); 32 | //创建tcc事务 33 | try { 34 | dtmClient.tccGlobalTransaction(dtmClient.genGid(), TccTestController::tccTrans); 35 | } catch (Exception e) { 36 | log.error("tccGlobalTransaction error", e); 37 | return "fail"; 38 | } 39 | return "success"; 40 | } 41 | 42 | 43 | /** 44 | * 具有子事务屏障功能的tcc demo (转账成功) 45 | * 46 | * @return 47 | */ 48 | @RequestMapping("tccBarrier") 49 | public String tccBarrier() { 50 | // 创建dmt client 51 | DtmClient dtmClient = new DtmClient(ipPort); 52 | //创建tcc事务 53 | try { 54 | dtmClient.tccGlobalTransaction(dtmClient.genGid(), TccTestController::tccBarrierTrans); 55 | } catch (Exception e) { 56 | log.error("tccGlobalTransaction error", e); 57 | return "fail"; 58 | } 59 | return "success"; 60 | } 61 | 62 | /** 63 | * 具有子事务屏障功能的tcc demo (转账失败) 64 | * 65 | * @return 66 | */ 67 | @RequestMapping("tccBarrierError") 68 | public String tccBarrierError() { 69 | // 创建dmt client 70 | DtmClient dtmClient = new DtmClient(ipPort); 71 | //创建tcc事务 72 | try { 73 | dtmClient.tccGlobalTransaction(dtmClient.genGid(), TccTestController::tccBarrierTransError); 74 | } catch (Exception e) { 75 | log.error("tccGlobalTransaction error", e); 76 | return "fail"; 77 | } 78 | return "success"; 79 | } 80 | 81 | 82 | /** 83 | * 定义tcc事务函数,内部需要通过callBranch注册事务子分支 84 | * 85 | * @param tcc 86 | * @return 87 | * @see TransController 88 | */ 89 | public static void tccTrans(Tcc tcc) throws Exception { 90 | Response outResponse = tcc 91 | .callBranch("", svc + "/TransOutTry", svc + "/TransOutConfirm", svc + "/TransOutCancel"); 92 | log.info("outResponse:{}", outResponse); 93 | Response inResponse = tcc.callBranch("", svc + "/TransInTry", svc + "/TransInConfirm", svc + "/TransInCancel"); 94 | log.info("inResponse:{}", inResponse); 95 | } 96 | 97 | 98 | /** 99 | * 定义tcc事务函数,内部需要通过callBranch注册事务子分支 100 | * 101 | * @param tcc 102 | * @return 103 | * @see TransBarrierController 104 | */ 105 | public static void tccBarrierTrans(Tcc tcc) throws Exception { 106 | // 用户1 转出30元 107 | Response outResponse = tcc 108 | .callBranch(new TransReq(1, -30), svc + "/barrierTransOutTry", svc + "/barrierTransOutConfirm", 109 | svc + "/barrierTransOutCancel"); 110 | log.info("outResponse:{}", outResponse); 111 | 112 | // 用户2 转入30元 113 | Response inResponse = tcc 114 | .callBranch(new TransReq(2, 30), svc + "/barrierTransInTry", svc + "/barrierTransInConfirm", 115 | svc + "/barrierTransInCancel"); 116 | log.info("inResponse:{}", inResponse); 117 | 118 | } 119 | 120 | /** 121 | * 定义tcc事务函数,内部需要通过callBranch注册事务子分支, 转账金额大于余额 转账失败 122 | * 123 | * @param tcc 124 | * @return 125 | * @see TransBarrierController 126 | */ 127 | public static void tccBarrierTransError(Tcc tcc) throws Exception { 128 | // 用户1 转出100000元 129 | Response outResponse = tcc 130 | .callBranch(new TransReq(1, -100000), svc + "/barrierTransOutTry", svc + "/barrierTransOutConfirm", 131 | svc + "/barrierTransOutCancel"); 132 | log.info("outResponse:{}", outResponse); 133 | 134 | // 用户2 转入100000元 135 | Response inResponse = tcc 136 | .callBranch(new TransReq(2, 100000), svc + "/barrierTransInTry", svc + "/barrierTransInConfirm", 137 | svc + "/barrierTransInCancel"); 138 | log.info("inResponse:{}", inResponse); 139 | 140 | } 141 | } -------------------------------------------------------------------------------- /src/main/java/com/dtmcli/java/sample/controller/TransBarrierController.java: -------------------------------------------------------------------------------- 1 | package com.dtmcli.java.sample.controller; 2 | 3 | import barrier.BranchBarrier; 4 | import com.alibaba.fastjson.JSON; 5 | import com.dtmcli.java.sample.param.TransReq; 6 | import com.dtmcli.java.sample.util.DataSourceUtil; 7 | import common.constant.Constant; 8 | import common.model.TransResponse; 9 | import common.utils.StreamUtil; 10 | import exception.FailureException; 11 | import lombok.extern.slf4j.Slf4j; 12 | import org.slf4j.Logger; 13 | import org.slf4j.LoggerFactory; 14 | import org.springframework.beans.factory.annotation.Autowired; 15 | import org.springframework.web.bind.annotation.RequestMapping; 16 | import org.springframework.web.bind.annotation.RestController; 17 | 18 | import javax.servlet.http.HttpServletRequest; 19 | import java.io.IOException; 20 | import java.sql.Connection; 21 | import java.sql.PreparedStatement; 22 | import java.sql.SQLException; 23 | 24 | @RestController 25 | @RequestMapping("api") 26 | @Slf4j 27 | public class TransBarrierController { 28 | 29 | Logger logger = LoggerFactory.getLogger(TransBarrierController.class); 30 | 31 | @Autowired 32 | private DataSourceUtil dataSourceUtil; 33 | 34 | 35 | @RequestMapping("barrierTransOutTry") 36 | public Object TransOutTry(HttpServletRequest request) throws Exception { 37 | 38 | BranchBarrier branchBarrier = new BranchBarrier(request.getParameterMap()); 39 | logger.info("barrierTransOutTry branchBarrier:{}", branchBarrier); 40 | 41 | TransReq transReq = extracted(request); 42 | Connection connection = dataSourceUtil.getConnecion(); 43 | branchBarrier.call(connection, (barrier) -> { 44 | System.out.println("用户: +" + transReq.getUserId() + ",转出" + Math.abs(transReq.getAmount()) + "元准备"); 45 | this.adjustTrading(connection, transReq); 46 | }); 47 | connection.close(); 48 | return TransResponse.buildTransResponse(Constant.SUCCESS_RESULT); 49 | } 50 | 51 | 52 | @RequestMapping("barrierTransOutConfirm") 53 | public Object TransOutConfirm(HttpServletRequest request) throws Exception { 54 | BranchBarrier branchBarrier = new BranchBarrier(request.getParameterMap()); 55 | logger.info("barrierTransOutConfirm branchBarrier:{}", branchBarrier); 56 | Connection connection = dataSourceUtil.getConnecion(); 57 | TransReq transReq = extracted(request); 58 | branchBarrier.call(connection, (barrier) -> { 59 | System.out.println("用户: +" + transReq.getUserId() + ",转出" + Math.abs(transReq.getAmount()) + "元提交"); 60 | adjustBalance(connection, transReq); 61 | }); 62 | connection.close(); 63 | return TransResponse.buildTransResponse(Constant.SUCCESS_RESULT); 64 | } 65 | 66 | @RequestMapping("barrierTransOutCancel") 67 | public Object TransOutCancel(HttpServletRequest request) throws Exception { 68 | BranchBarrier branchBarrier = new BranchBarrier(request.getParameterMap()); 69 | logger.info("barrierTransOutCancel branchBarrier:{}", branchBarrier); 70 | TransReq transReq = extracted(request); 71 | Connection connection = dataSourceUtil.getConnecion(); 72 | branchBarrier.call(connection, (barrier) -> { 73 | System.out.println("用户: +" + transReq.getUserId() + ",转出" + Math.abs(transReq.getAmount()) + "元回滚"); 74 | this.adjustTrading(connection, transReq); 75 | }); 76 | connection.close(); 77 | return TransResponse.buildTransResponse(Constant.SUCCESS_RESULT); 78 | } 79 | 80 | @RequestMapping("barrierTransInTry") 81 | public Object TransInTry(HttpServletRequest request) throws Exception { 82 | BranchBarrier branchBarrier = new BranchBarrier(request.getParameterMap()); 83 | logger.info("barrierTransInTry branchBarrier:{}", branchBarrier); 84 | Connection connection = dataSourceUtil.getConnecion(); 85 | TransReq transReq = extracted(request); 86 | branchBarrier.call(connection, (barrier) -> { 87 | System.out.println("用户: +" + transReq.getUserId() + ",转入" + Math.abs(transReq.getAmount()) + "元准备"); 88 | this.adjustTrading(connection, transReq); 89 | }); 90 | connection.close(); 91 | return TransResponse.buildTransResponse(Constant.SUCCESS_RESULT); 92 | } 93 | 94 | @RequestMapping("barrierTransInConfirm") 95 | public Object TransInConfirm(HttpServletRequest request) throws Exception { 96 | BranchBarrier branchBarrier = new BranchBarrier(request.getParameterMap()); 97 | logger.info("barrierTransInConfirm TransInCancel branchBarrier:{}", branchBarrier); 98 | Connection connection = dataSourceUtil.getConnecion(); 99 | TransReq transReq = extracted(request); 100 | branchBarrier.call(connection, (barrier) -> { 101 | System.out.println("用户: +" + transReq.getUserId() + ",转入" + Math.abs(transReq.getAmount()) + "元提交"); 102 | adjustBalance(connection, transReq); 103 | }); 104 | connection.close(); 105 | return TransResponse.buildTransResponse(Constant.SUCCESS_RESULT); 106 | } 107 | 108 | @RequestMapping("barrierTransInCancel") 109 | public Object TransInCancel(HttpServletRequest request) throws Exception { 110 | BranchBarrier branchBarrier = new BranchBarrier(request.getParameterMap()); 111 | logger.info("barrierTransInCancel branchBarrier:{}", branchBarrier); 112 | Connection connection = dataSourceUtil.getConnecion(); 113 | TransReq transReq = extracted(request); 114 | branchBarrier.call(connection, (barrier) -> { 115 | System.out.println("用户: +" + transReq.getUserId() + ",转入" + Math.abs(transReq.getAmount()) + "回滚"); 116 | this.adjustTrading(connection, transReq); 117 | }); 118 | connection.close(); 119 | return TransResponse.buildTransResponse(Constant.SUCCESS_RESULT); 120 | } 121 | 122 | /** 123 | * 提取body中参数 124 | * 125 | * @param request 126 | * @return 127 | * @throws IOException 128 | */ 129 | private TransReq extracted(HttpServletRequest request) throws IOException { 130 | byte[] bytes = StreamUtil.copyToByteArray(request.getInputStream()); 131 | return JSON.parseObject(bytes, TransReq.class); 132 | } 133 | 134 | /** 135 | * 更新交易金额 136 | * 137 | * @param connection 138 | * @param transReq 139 | * @throws SQLException 140 | */ 141 | public void adjustTrading(Connection connection, TransReq transReq) throws Exception { 142 | String sql = "update dtm_busi.user_account set trading_balance=trading_balance+?" 143 | + " where user_id=? and trading_balance + ? + balance >= 0"; 144 | PreparedStatement preparedStatement = null; 145 | try { 146 | preparedStatement = connection.prepareStatement(sql); 147 | preparedStatement.setInt(1, transReq.getAmount()); 148 | preparedStatement.setInt(2, transReq.getUserId()); 149 | preparedStatement.setInt(3, transReq.getAmount()); 150 | if (preparedStatement.executeUpdate() > 0) { 151 | System.out.println("交易金额更新成功"); 152 | } else { 153 | throw new FailureException("交易失败"); 154 | } 155 | } finally { 156 | if (null != preparedStatement) { 157 | preparedStatement.close(); 158 | } 159 | } 160 | 161 | } 162 | 163 | /** 164 | * 更新余额 165 | */ 166 | public void adjustBalance(Connection connection, TransReq transReq) throws SQLException { 167 | PreparedStatement preparedStatement = null; 168 | try { 169 | String sql = "update dtm_busi.user_account set trading_balance=trading_balance-?,balance=balance+? where user_id=?"; 170 | preparedStatement = connection.prepareStatement(sql); 171 | preparedStatement.setInt(1, transReq.getAmount()); 172 | preparedStatement.setInt(2, transReq.getAmount()); 173 | preparedStatement.setInt(3, transReq.getUserId()); 174 | if (preparedStatement.executeUpdate() > 0) { 175 | System.out.println("余额更新成功"); 176 | } 177 | } finally { 178 | if (null != preparedStatement) { 179 | preparedStatement.close(); 180 | } 181 | } 182 | } 183 | 184 | } -------------------------------------------------------------------------------- /dtmcli-java-sample.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | --------------------------------------------------------------------------------