English | 简体中文
dtm-spring-boot-starter is java sdk based on spring boot for dtm, spring boot 2.x version is required.
Now this sdk supports following distributed transaction features:
- TCC
- Saga
- two-phase commit
- pom file
<dependency>
<groupId>com.jsrdxzw.github</groupId>
<artifactId>dtm-spring-boot-starter</artifactId>
<version>1.1.0</version>
</dependency>
- dtm server configuration
dtm:
http-server: http://localhost:36789/api/dtmsvr # dtm server address
# your project configuration
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
username:
password:
url: jdbc:mysql://localhost:3306/{project}
- execute sql files in dtm
- dtmcli.barrier.mysql.sql.
- If you want to use barrier,create
barrier table
using dtmsvr.storage.mysql.sql.
- use
@EnableDtm
to start auto-configuration in spring boot.
@SpringBootApplication
@EnableDtm
public class DtmSpringBootExampleApplication {
public static void main(String[] args) {
SpringApplication.run(DtmSpringBootExampleApplication.class, args);
}
}
AP Usage
public void doSomething() {
TransReq req = new TransReq();
req.setAmount(BigDecimal.valueOf(100));
DtmServerResult result = new Saga(httpClient)
.add(HOST + "/SagaBTransOut", HOST + "/SagaBTransOutCom", req)
.add(HOST + "/SagaBTransIn", HOST + "/SagaBTransInCom", req)
.submit();
}
DM Usage
@DtmResponse
@PostMapping("/SagaBTransOut")
public ResultData sagaTransOut(@DtmBarrier BranchBarrier branchBarrier, @RequestBody TransReq transReq) throws Exception {
branchBarrier.call(transactionManager, barrier -> {
userAccountMapper.sagaAdjustBalance(TRANSOUT_UID, transReq.getAmount().negate());
});
return ResultData.success();
}
@DtmResponse
@PostMapping("/SagaBTransIn")
public ResultData sagaTransIn(@DtmBarrier BranchBarrier branchBarrier, @RequestBody TransReq transReq) throws Exception {
branchBarrier.call(transactionManager, barrier -> {
userAccountMapper.sagaAdjustBalance(TRANSIN_UID, transReq.getAmount());
});
return ResultData.success();
}
@DtmResponse
@PostMapping("/SagaBTransOutCom")
public ResultData sagaTransOutCom(@DtmBarrier BranchBarrier branchBarrier, @RequestBody TransReq transReq) throws Exception {
branchBarrier.call(transactionManager, barrier -> {
userAccountMapper.sagaAdjustBalance(TRANSOUT_UID, transReq.getAmount());
});
return ResultData.success();
}
@DtmResponse
@PostMapping("/SagaBTransInCom")
public ResultData sagaTransInCom(@DtmBarrier BranchBarrier branchBarrier, @RequestBody TransReq transReq) throws Exception {
branchBarrier.call(transactionManager, barrier -> {
userAccountMapper.sagaAdjustBalance(2, transReq.getAmount().negate());
});
return ResultData.success();
}
AP Usage
public void doSomething() {
TransReq transReq = TransReq.builder().amount(BigDecimal.valueOf(30)).build();
new Tcc(httpClient).tccGlobalTransaction(tcc -> {
tcc.callBranch(
transReq, HOST + "/tccTransOutTry", HOST + "/tccTransOutConfirm", HOST + "/tccTransOutCancel");
tcc.callBranch(
transReq, HOST + "/tccTransInTry", HOST + "/tccTransInConfirm", HOST + "/tccTransInCancel");
});
}
DM Usage
@DtmResponse
@PostMapping("/tccTransInTry")
public ResultData tccTransInTry(@DtmBarrier BranchBarrier branchBarrier, @RequestBody TransReq transReq) throws Exception {
branchBarrier.call(transactionManager, barrier -> {
userAccountMapper.tccAdjustTrading(TRANSIN_UID, transReq.getAmount());
});
return ResultData.success();
}
@DtmResponse
@PostMapping("/tccTransInConfirm")
public ResultData tccTransInConfirm(@DtmBarrier BranchBarrier branchBarrier, @RequestBody TransReq transReq) throws Exception {
branchBarrier.call(transactionManager, barrier -> {
userAccountMapper.tccAdjustBalance(TRANSIN_UID, transReq.getAmount());
});
return ResultData.success();
}
@DtmResponse
@PostMapping("/tccTransInCancel")
public ResultData tccTransInCancel(@DtmBarrier BranchBarrier branchBarrier, @RequestBody TransReq transReq) throws Exception {
branchBarrier.call(transactionManager, barrier -> {
userAccountMapper.tccAdjustTrading(TRANSIN_UID, transReq.getAmount().negate());
});
return ResultData.success();
}
// ...
public void doSomething() {
TransReq req = TransReq.builder().amount(BigDecimal.valueOf(30)).build();
Msg msg = new Msg(httpClient).add(HOST + "/SagaBTransOut", req).add(HOST + "/SagaBTransIn", req);
msg.prepare(HOST + "/query");
// ... your business logic
msg.submit();
}
commit and query
@GetMapping("/query")
public DtmServerResult queryDtm(@DtmBarrier BranchBarrier branchBarrier) {
branchBarrier.queryPrepared(transactionManager);
DtmServerResult dtmServerResult = new DtmServerResult();
dtmServerResult.setResult(DtmResultEnum.SUCCESS);
return dtmServerResult;
}
@PostMapping("/http_msg_doAndCommit")
public String httpMsgDoAndCommit() {
TransReq req = TransReq.builder().amount(BigDecimal.valueOf(200)).build();
Msg msg = new Msg(dtmHttpClient).add(host + "/SagaBTransIn", req);
msg.doAndSubmitDb(transactionManager, host + "/query", barrier -> {
System.out.println("submit transout");
userAccountMapper.sagaAdjustBalance(TRANSOUT_UID, req.getAmount().negate());
});
return "ok";
}
please see dtm-spring-boot-starter examples to learn more details.