新增seata官方演示demo替换成spring-flex结合演示

This commit is contained in:
life 2023-08-08 20:43:57 +08:00
parent d654d10ac8
commit e0f287fffd
35 changed files with 1812 additions and 2 deletions

View File

@ -88,6 +88,6 @@ public class FlexSpringTransaction implements Transaction {
@Override @Override
public Integer getTimeout() throws SQLException { public Integer getTimeout() throws SQLException {
return getConnection().getNetworkTimeout(); return null;
} }
} }

View File

@ -0,0 +1,30 @@
/*
* Copyright 1999-2021 Seata.io Group.
*
* 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
*
* http://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 mybatisflex.test.acount.accountservice.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
return restTemplate;
}
}

View File

@ -0,0 +1,38 @@
/*
* Copyright 1999-2021 Seata.io Group.
*
* 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
*
* http://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 mybatisflex.test.acount.accountservice.controller;
import io.seata.core.context.RootContext;
import java.math.BigDecimal;
import mybatisflex.test.acount.accountservice.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class AccountController {
@Autowired
AccountService accountService;
@GetMapping
public void debit(@RequestParam String userId, @RequestParam BigDecimal orderMoney) {
System.out.println("account XID " + RootContext.getXID());
accountService.debit(userId, orderMoney);
}
}

View File

@ -0,0 +1,50 @@
/*
* Copyright 1999-2021 Seata.io Group.
*
* 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
*
* http://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 mybatisflex.test.acount.accountservice.persistence;
import java.math.BigDecimal;
public class Account {
private Integer id;
private String userId;
private BigDecimal money;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public BigDecimal getMoney() {
return money;
}
public void setMoney(BigDecimal money) {
this.money = money;
}
}

View File

@ -0,0 +1,28 @@
/*
* Copyright 1999-2021 Seata.io Group.
*
* 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
*
* http://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 mybatisflex.test.acount.accountservice.persistence;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@Mapper
public interface AccountMapper {
Account selectByUserId(@Param("userId") String userId);
int updateById(Account record);
}

View File

@ -0,0 +1,42 @@
/*
* Copyright 1999-2021 Seata.io Group.
*
* 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
*
* http://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 mybatisflex.test.acount.accountservice.service;
import java.math.BigDecimal;
import mybatisflex.test.acount.accountservice.persistence.Account;
import mybatisflex.test.acount.accountservice.persistence.AccountMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class AccountService {
private static final String ERROR_USER_ID = "1002";
@Autowired
private AccountMapper accountMapper;
public void debit(String userId, BigDecimal num) {
Account account = accountMapper.selectByUserId(userId);
account.setMoney(account.getMoney().subtract(num));
accountMapper.updateById(account);
if (ERROR_USER_ID.equals(userId)) {
throw new RuntimeException("account branch exception");
}
}
}

View File

@ -0,0 +1,129 @@
server:
port: 8083
mybatis-flex:
seata-config:
enable: true #启动seata
seata-mode: XA #xa或者ta
datasource:
accountdb:
url: jdbc:mysql://127.0.0.1:3306/db_account
username: root
password: 131496
spring:
main:
allow-circular-references: true
#spring:
# datasource:
# type: com.alibaba.druid.pool.DruidDataSource
# driver-class-name: com.mysql.jdbc.Driver
# url: jdbc:mysql://127.0.0.1:3306/db_account?useSSL=false&serverTimezone=UTC
# username: root
# password: 131496
seata:
enabled: true
application-id: account-service
tx-service-group: my_test_tx_group
enable-auto-data-source-proxy: false
#use-jdk-proxy: false
client:
rm:
async-commit-buffer-limit: 1000
report-retry-count: 5
table-meta-check-enable: false
report-success-enable: false
lock:
retry-interval: 10
retry-times: 30
retry-policy-branch-rollback-on-conflict: true
tm:
commit-retry-count: 5
rollback-retry-count: 5
undo:
data-validation: true
log-serialization: jackson
log-table: undo_log
log:
exceptionRate: 100
service:
vgroup-mapping:
my_test_tx_group: default
grouplist:
default: 127.0.0.1:8091
#enable-degrade: false
#disable-global-transaction: false
transport:
shutdown:
wait: 3
thread-factory:
boss-thread-prefix: NettyBoss
worker-thread-prefix: NettyServerNIOWorker
server-executor-thread-prefix: NettyServerBizHandler
share-boss-worker: false
client-selector-thread-prefix: NettyClientSelector
client-selector-thread-size: 1
client-worker-thread-prefix: NettyClientWorkerThread
worker-thread-size: default
boss-thread-size: 1
type: TCP
server: NIO
heartbeat: true
serialization: seata
compressor: none
enable-client-batch-send-request: true
config:
type: file
consul:
server-addr: 127.0.0.1:8500
apollo:
apollo-meta: http://192.168.1.204:8801
app-id: seata-server
namespace: application
etcd3:
server-addr: http://localhost:2379
nacos:
namespace:
serverAddr: localhost
group: SEATA_GROUP
zk:
server-addr: 127.0.0.1:2181
session-timeout: 6000
connect-timeout: 2000
username: ""
password: ""
registry:
type: file
consul:
cluster: default
server-addr: 127.0.0.1:8500
etcd3:
cluster: default
serverAddr: http://localhost:2379
eureka:
application: default
weight: 1
service-url: http://localhost:8761/eureka
nacos:
cluster: default
server-addr: localhost
namespace:
redis:
server-addr: localhost:6379
db: 0
password:
cluster: default
timeout: 0
sofa:
server-addr: 127.0.0.1:9603
application: default
region: DEFAULT_ZONE
datacenter: DefaultDataCenter
cluster: default
group: SEATA_GROUP
addressWaitTime: 3000
zk:
cluster: default
server-addr: 127.0.0.1:2181
session-timeout: 6000
connect-timeout: 2000
username: ""
password: ""

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="mybatisflex.test.acount.accountservice.persistence.AccountMapper">
<resultMap id="BaseResultMap" type="mybatisflex.test.acount.accountservice.persistence.Account">
<id column="id" property="id" jdbcType="INTEGER"/>
<result column="user_id" property="userId" jdbcType="VARCHAR"/>
<result column="money" property="money" jdbcType="DECIMAL"/>
</resultMap>
<select id="selectByUserId" resultType="mybatisflex.test.acount.accountservice.persistence.Account">
select id, user_id, money
from account_tbl
WHERE user_id = #{userId}
</select>
<update id="updateById" parameterType="mybatisflex.test.acount.accountservice.persistence.Account">
update account_tbl
set money = #{money,jdbcType=DECIMAL}
where id = #{id}
</update>
</mapper>

View File

@ -0,0 +1,37 @@
/*
* Copyright 1999-2021 Seata.io Group.
*
* 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
*
* http://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 mybatisflex.test.businessservice.client;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
@Component
public class OrderClient {
@Autowired
private RestTemplate restTemplate;
public void create(String userId, String commodityCode, int orderCount) {
String url = "http://127.0.0.1:8082/api/order/debit?userId=" + userId + "&commodityCode=" + commodityCode
+ "&count=" + orderCount;
try {
restTemplate.getForEntity(url, Void.class);
} catch (Exception e) {
throw new RuntimeException(String.format("create url %s ,error:", url));
}
}
}

View File

@ -0,0 +1,38 @@
/*
* Copyright 1999-2021 Seata.io Group.
*
* 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
*
* http://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 mybatisflex.test.businessservice.client;
import io.seata.core.context.RootContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
@Component
public class StockClient {
@Autowired
private RestTemplate restTemplate;
public void deduct(String commodityCode, int orderCount) {
System.out.println("business to stock " + RootContext.getXID());
String url = "http://127.0.0.1:8081/api/stock/deduct?commodityCode=" + commodityCode + "&count=" + orderCount;
try {
restTemplate.getForEntity(url, Void.class);
} catch (Exception e) {
throw new RuntimeException(String.format("deduct url %s ,error:",url),e);
}
}
}

View File

@ -0,0 +1,30 @@
/*
* Copyright 1999-2021 Seata.io Group.
*
* 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
*
* http://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 mybatisflex.test.businessservice.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
return restTemplate;
}
}

View File

@ -0,0 +1,58 @@
/*
* Copyright 1999-2021 Seata.io Group.
*
* 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
*
* http://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 mybatisflex.test.businessservice.controller;
import javax.servlet.http.HttpServletRequest;
import mybatisflex.test.businessservice.service.BusinessService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/api/business")
@RestController
public class BusinessController {
@Autowired
private BusinessService businessService;
/**
* 购买下单模拟全局事务提交
*
* @return
*/
@RequestMapping("/purchase/commit")
public Boolean purchaseCommit(HttpServletRequest request) {
businessService.purchase("1001", "2001", 1);
return true;
}
/**
* 购买下单模拟全局事务回滚
*
* @return
*/
@RequestMapping("/purchase/rollback")
public Boolean purchaseRollback() {
try {
businessService.purchase("1002", "2001", 1);
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
}

View File

@ -0,0 +1,50 @@
/*
* Copyright 1999-2021 Seata.io Group.
*
* 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
*
* http://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 mybatisflex.test.businessservice.service;
import io.seata.core.context.RootContext;
import io.seata.spring.annotation.GlobalTransactional;
import mybatisflex.test.businessservice.client.OrderClient;
import mybatisflex.test.businessservice.client.StockClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class BusinessService {
private static final Logger LOGGER = LoggerFactory.getLogger(BusinessService.class);
@Autowired
private StockClient stockClient;
@Autowired
private OrderClient orderClient;
/**
* 减库存下订单
*
* @param userId
* @param commodityCode
* @param orderCount
*/
@GlobalTransactional
public void purchase(String userId, String commodityCode, int orderCount) {
LOGGER.info("purchase begin ... xid: " + RootContext.getXID());
stockClient.deduct(commodityCode, orderCount);
orderClient.create(userId, commodityCode, orderCount);
}
}

View File

@ -0,0 +1,113 @@
server:
port: 8084
spring:
main:
allow-circular-references: true
seata:
enabled: true
application-id: business-service
tx-service-group: my_test_tx_group
enable-auto-data-source-proxy: false
#use-jdk-proxy: false
client:
rm:
async-commit-buffer-limit: 1000
report-retry-count: 5
table-meta-check-enable: false
report-success-enable: false
lock:
retry-interval: 10
retry-times: 30
retry-policy-branch-rollback-on-conflict: true
tm:
commit-retry-count: 5
rollback-retry-count: 5
undo:
data-validation: true
log-serialization: jackson
log-table: undo_log
log:
exceptionRate: 100
service:
vgroup-mapping:
my_test_tx_group: default
grouplist:
default: 127.0.0.1:8091
#enable-degrade: false
#disable-global-transaction: false
transport:
shutdown:
wait: 3
thread-factory:
boss-thread-prefix: NettyBoss
worker-thread-prefix: NettyServerNIOWorker
server-executor-thread-prefix: NettyServerBizHandler
share-boss-worker: false
client-selector-thread-prefix: NettyClientSelector
client-selector-thread-size: 1
client-worker-thread-prefix: NettyClientWorkerThread
worker-thread-size: default
boss-thread-size: 1
type: TCP
server: NIO
heartbeat: true
serialization: seata
compressor: none
enable-client-batch-send-request: true
config:
type: file
consul:
server-addr: 127.0.0.1:8500
apollo:
apollo-meta: http://192.168.1.204:8801
app-id: seata-server
namespace: application
etcd3:
server-addr: http://localhost:2379
nacos:
namespace:
serverAddr: localhost
group: SEATA_GROUP
zk:
server-addr: 127.0.0.1:2181
session-timeout: 6000
connect-timeout: 2000
username: ""
password: ""
registry:
type: file
consul:
cluster: default
server-addr: 127.0.0.1:8500
etcd3:
cluster: default
serverAddr: http://localhost:2379
eureka:
application: default
weight: 1
service-url: http://localhost:8761/eureka
nacos:
cluster: default
server-addr: localhost
namespace:
redis:
server-addr: localhost:6379
db: 0
password:
cluster: default
timeout: 0
sofa:
server-addr: 127.0.0.1:9603
application: default
region: DEFAULT_ZONE
datacenter: DefaultDataCenter
cluster: default
group: SEATA_GROUP
addressWaitTime: 3000
zk:
cluster: default
server-addr: 127.0.0.1:2181
session-timeout: 6000
connect-timeout: 2000
username: ""
password: ""

View File

@ -0,0 +1,59 @@
/*
* Copyright 1999-2021 Seata.io Group.
*
* 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
*
* http://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 mybatisflex.test.commonservice.config;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import javax.annotation.PostConstruct;
import mybatisflex.test.commonservice.interceptor.SeataRestTemplateInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.web.client.RestTemplate;
@Configuration
public class SeataRestTemplateAutoConfiguration {
@Autowired(required = false)
private Collection<RestTemplate> restTemplates;
@Autowired
private SeataRestTemplateInterceptor seataRestTemplateInterceptor;
public SeataRestTemplateAutoConfiguration() {
}
@Bean
public SeataRestTemplateInterceptor seataRestTemplateInterceptor() {
return new SeataRestTemplateInterceptor();
}
@PostConstruct
public void init() {
if (this.restTemplates != null) {
Iterator var1 = this.restTemplates.iterator();
while (var1.hasNext()) {
RestTemplate restTemplate = (RestTemplate)var1.next();
List<ClientHttpRequestInterceptor> interceptors = new ArrayList(restTemplate.getInterceptors());
interceptors.add(this.seataRestTemplateInterceptor);
restTemplate.setInterceptors(interceptors);
}
}
}
}

View File

@ -0,0 +1,58 @@
/*
* Copyright 1999-2021 Seata.io Group.
*
* 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
*
* http://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 mybatisflex.test.commonservice.filter;
import io.seata.core.context.RootContext;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;
@Component
public class SeataFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest)servletRequest;
String xid = req.getHeader(RootContext.KEY_XID.toLowerCase());
boolean isBind = false;
if (StringUtils.isNotBlank(xid)) {
RootContext.bind(xid);
isBind = true;
}
try {
filterChain.doFilter(servletRequest, servletResponse);
} finally {
if (isBind) {
RootContext.unbind();
}
}
}
@Override
public void destroy() {
}
}

View File

@ -0,0 +1,44 @@
/*
* Copyright 1999-2021 Seata.io Group.
*
* 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
*
* http://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 mybatisflex.test.commonservice.interceptor;
import io.seata.core.context.RootContext;
import java.io.IOException;
import org.apache.commons.lang.StringUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.client.support.HttpRequestWrapper;
import org.springframework.stereotype.Component;
public class SeataRestTemplateInterceptor implements ClientHttpRequestInterceptor {
public SeataRestTemplateInterceptor() {
}
public ClientHttpResponse intercept(HttpRequest httpRequest, byte[] bytes,
ClientHttpRequestExecution clientHttpRequestExecution) throws IOException {
HttpRequestWrapper requestWrapper = new HttpRequestWrapper(httpRequest);
String xid = RootContext.getXID();
if (StringUtils.isNotEmpty(xid)) {
requestWrapper.getHeaders().add(RootContext.KEY_XID, xid);
}
return clientHttpRequestExecution.execute(requestWrapper, bytes);
}
}

View File

@ -0,0 +1,37 @@
/*
* Copyright 1999-2021 Seata.io Group.
*
* 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
*
* http://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 mybatisflex.test.orderservice.client;
import java.math.BigDecimal;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
@Component
public class AccountClient {
@Autowired
private RestTemplate restTemplate;
public void debit(String userId, BigDecimal orderMoney) {
String url = "http://127.0.0.1:8083?userId=" + userId + "&orderMoney=" + orderMoney;
try {
restTemplate.getForEntity(url, Void.class);
} catch (Exception e) {
throw new RuntimeException(String.format("debit url %s ,error:",url),e);
}
}
}

View File

@ -0,0 +1,30 @@
/*
* Copyright 1999-2021 Seata.io Group.
*
* 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
*
* http://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 mybatisflex.test.orderservice.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
return restTemplate;
}
}

View File

@ -0,0 +1,39 @@
/*
* Copyright 1999-2021 Seata.io Group.
*
* 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
*
* http://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 mybatisflex.test.orderservice.controller;
import io.seata.core.context.RootContext;
import mybatisflex.test.orderservice.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/api/order")
@RestController
public class OrderController {
@Autowired
OrderService orderService;
@GetMapping(value = "/debit")
public void debit(@RequestParam String userId, @RequestParam String commodityCode, @RequestParam Integer count) {
System.out.println("order XID " + RootContext.getXID());
orderService.create(userId, commodityCode, count);
}
}

View File

@ -0,0 +1,70 @@
/*
* Copyright 1999-2021 Seata.io Group.
*
* 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
*
* http://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 mybatisflex.test.orderservice.persistence;
import java.math.BigDecimal;
public class Order {
private Integer id;
private String userId;
private String commodityCode;
private Integer count;
private BigDecimal money;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getCommodityCode() {
return commodityCode;
}
public void setCommodityCode(String commodityCode) {
this.commodityCode = commodityCode;
}
public Integer getCount() {
return count;
}
public void setCount(Integer count) {
this.count = count;
}
public BigDecimal getMoney() {
return money;
}
public void setMoney(BigDecimal money) {
this.money = money;
}
}

View File

@ -0,0 +1,25 @@
/*
* Copyright 1999-2021 Seata.io Group.
*
* 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
*
* http://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 mybatisflex.test.orderservice.persistence;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface OrderMapper {
int insert(Order record);
}

View File

@ -0,0 +1,47 @@
/*
* Copyright 1999-2021 Seata.io Group.
*
* 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
*
* http://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 mybatisflex.test.orderservice.service;
import java.math.BigDecimal;
import mybatisflex.test.orderservice.client.AccountClient;
import mybatisflex.test.orderservice.persistence.Order;
import mybatisflex.test.orderservice.persistence.OrderMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class OrderService {
@Autowired
private AccountClient accountClient;
@Autowired
private OrderMapper orderMapper;
public void create(String userId, String commodityCode, Integer count) {
BigDecimal orderMoney = new BigDecimal(count).multiply(new BigDecimal(5));
Order order = new Order();
order.setUserId(userId);
order.setCommodityCode(commodityCode);
order.setCount(count);
order.setMoney(orderMoney);
orderMapper.insert(order);
accountClient.debit(userId, orderMoney);
}
}

View File

@ -0,0 +1,129 @@
server:
port: 8082
mybatis-flex:
seata-config:
enable: true #启动seata
seata-mode: XA #xa或者ta
datasource:
orderdb:
url: jdbc:mysql://127.0.0.1:3306/db_order
username: root
password: 131496
spring:
main:
allow-circular-references: true
#spring:
# datasource:
# type: com.alibaba.druid.pool.DruidDataSource
# driver-class-name: com.mysql.jdbc.Driver
# url: jdbc:mysql://127.0.0.1:3306/db_order?useSSL=false&serverTimezone=UTC
# username: root
# password: 131496
seata:
enabled: true
application-id: order-service
tx-service-group: my_test_tx_group
enable-auto-data-source-proxy: false
#use-jdk-proxy: false
client:
rm:
async-commit-buffer-limit: 1000
report-retry-count: 5
table-meta-check-enable: false
report-success-enable: false
lock:
retry-interval: 10
retry-times: 30
retry-policy-branch-rollback-on-conflict: true
tm:
commit-retry-count: 5
rollback-retry-count: 5
undo:
data-validation: true
log-serialization: jackson
log-table: undo_log
log:
exceptionRate: 100
service:
vgroup-mapping:
my_test_tx_group: default
grouplist:
default: 127.0.0.1:8091
#enable-degrade: false
#disable-global-transaction: false
transport:
shutdown:
wait: 3
thread-factory:
boss-thread-prefix: NettyBoss
worker-thread-prefix: NettyServerNIOWorker
server-executor-thread-prefix: NettyServerBizHandler
share-boss-worker: false
client-selector-thread-prefix: NettyClientSelector
client-selector-thread-size: 1
client-worker-thread-prefix: NettyClientWorkerThread
worker-thread-size: default
boss-thread-size: 1
type: TCP
server: NIO
heartbeat: true
serialization: seata
compressor: none
enable-client-batch-send-request: true
config:
type: file
consul:
server-addr: 127.0.0.1:8500
apollo:
apollo-meta: http://192.168.1.204:8801
app-id: seata-server
namespace: application
etcd3:
server-addr: http://localhost:2379
nacos:
namespace:
serverAddr: localhost
group: SEATA_GROUP
zk:
server-addr: 127.0.0.1:2181
session-timeout: 6000
connect-timeout: 2000
username: ""
password: ""
registry:
type: file
consul:
cluster: default
server-addr: 127.0.0.1:8500
etcd3:
cluster: default
serverAddr: http://localhost:2379
eureka:
application: default
weight: 1
service-url: http://localhost:8761/eureka
nacos:
cluster: default
server-addr: localhost
namespace:
redis:
server-addr: localhost:6379
db: 0
password:
cluster: default
timeout: 0
sofa:
server-addr: 127.0.0.1:9603
application: default
region: DEFAULT_ZONE
datacenter: DefaultDataCenter
cluster: default
group: SEATA_GROUP
addressWaitTime: 3000
zk:
cluster: default
server-addr: 127.0.0.1:2181
session-timeout: 6000
connect-timeout: 2000
username: ""
password: ""

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="mybatisflex.test.orderservice.persistence.OrderMapper">
<resultMap id="BaseResultMap" type="mybatisflex.test.orderservice.persistence.Order">
<id column="id" property="id" jdbcType="INTEGER"/>
<result column="user_id" property="userId" jdbcType="VARCHAR"/>
<result column="commodity_code" property="commodityCode" jdbcType="VARCHAR"/>
<result column="count" property="count" jdbcType="INTEGER"/>
<result column="money" property="money" jdbcType="DECIMAL"/>
</resultMap>
<insert id="insert" parameterType="mybatisflex.test.orderservice.persistence.Order">
insert into order_tbl (user_id, commodity_code, count, money)
values (#{userId,jdbcType=VARCHAR}, #{commodityCode,jdbcType=VARCHAR}, #{count,jdbcType=INTEGER},
#{money,jdbcType=DECIMAL})
</insert>
</mapper>

View File

@ -0,0 +1,97 @@
# Account
DROP SCHEMA IF EXISTS db_account;
CREATE SCHEMA db_account;
USE db_account;
CREATE TABLE `account_tbl`
(
`id` INT(11) NOT NULL AUTO_INCREMENT,
`user_id` VARCHAR(255) DEFAULT NULL,
`money` INT(11) DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8;
INSERT INTO account_tbl (id, user_id, money)
VALUES (1, '1001', 10000);
INSERT INTO account_tbl (id, user_id, money)
VALUES (2, '1002', 10000);
CREATE TABLE `undo_log`
(
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`branch_id` bigint(20) NOT NULL,
`xid` varchar(100) NOT NULL,
`context` varchar(128) NOT NULL,
`rollback_info` longblob NOT NULL,
`log_status` int(11) NOT NULL,
`log_created` datetime NOT NULL,
`log_modified` datetime NOT NULL,
`ext` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
# Order
DROP SCHEMA IF EXISTS db_order;
CREATE SCHEMA db_order;
USE db_order;
CREATE TABLE `order_tbl`
(
`id` INT(11) NOT NULL AUTO_INCREMENT,
`user_id` VARCHAR(255) DEFAULT NULL,
`commodity_code` VARCHAR(255) DEFAULT NULL,
`count` INT(11) DEFAULT '0',
`money` INT(11) DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8;
CREATE TABLE `undo_log`
(
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`branch_id` bigint(20) NOT NULL,
`xid` varchar(100) NOT NULL,
`context` varchar(128) NOT NULL,
`rollback_info` longblob NOT NULL,
`log_status` int(11) NOT NULL,
`log_created` datetime NOT NULL,
`log_modified` datetime NOT NULL,
`ext` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
# stock
DROP SCHEMA IF EXISTS db_stock;
CREATE SCHEMA db_stock;
USE db_stock;
CREATE TABLE `stock_tbl`
(
`id` INT(11) NOT NULL AUTO_INCREMENT,
`commodity_code` VARCHAR(255) DEFAULT NULL,
`count` INT(11) DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `commodity_code` (`commodity_code`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8;
INSERT INTO stock_tbl (id, commodity_code, count)
VALUES (1, '2001', 1000);
CREATE TABLE `undo_log`
(
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`branch_id` bigint(20) NOT NULL,
`xid` varchar(100) NOT NULL,
`context` varchar(128) NOT NULL,
`rollback_info` longblob NOT NULL,
`log_status` int(11) NOT NULL,
`log_created` datetime NOT NULL,
`log_modified` datetime NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

View File

@ -0,0 +1,30 @@
/*
* Copyright 1999-2021 Seata.io Group.
*
* 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
*
* http://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 mybatisflex.test.stockservice.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
return restTemplate;
}
}

View File

@ -0,0 +1,65 @@
/*
* Copyright 1999-2021 Seata.io Group.
*
* 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
*
* http://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 mybatisflex.test.stockservice.controller;
import io.seata.core.context.RootContext;
import java.sql.SQLException;
import mybatisflex.test.stockservice.persistence.Stock;
import mybatisflex.test.stockservice.service.StockService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/api/stock")
@RestController
public class StockController {
@Autowired
StockService stockService;
@GetMapping(value = "/deduct")
public void deduct(@RequestParam String commodityCode, @RequestParam Integer count) throws SQLException {
System.out.println("stock XID " + RootContext.getXID());
stockService.deduct(commodityCode, count);
}
@GetMapping(value = "/get/{id}")
public Stock getById(@PathVariable("id") Integer id) {
return stockService.get(id);
}
@GetMapping(value = "/batch/update")
public void batchUpdateCond() {
try {
stockService.batchUpdate();
} catch (SQLException e) {
e.printStackTrace();
}
}
@GetMapping(value = "/batch/delete")
public void batchDeleteCond() {
try {
stockService.batchDelete();
} catch (SQLException e) {
e.printStackTrace();
}
}
}

View File

@ -0,0 +1,48 @@
/*
* Copyright 1999-2021 Seata.io Group.
*
* 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
*
* http://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 mybatisflex.test.stockservice.persistence;
public class Stock {
private Integer id;
private String commodityCode;
private Integer count;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getCommodityCode() {
return commodityCode;
}
public void setCommodityCode(String commodityCode) {
this.commodityCode = commodityCode;
}
public Integer getCount() {
return count;
}
public void setCount(Integer count) {
this.count = count;
}
}

View File

@ -0,0 +1,36 @@
/*
* Copyright 1999-2021 Seata.io Group.
*
* 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
*
* http://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 mybatisflex.test.stockservice.persistence;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@Mapper
public interface StockMapper {
Stock selectById(@Param("id") Integer id);
Stock findByCommodityCode(@Param("commodityCode") String commodityCode);
int updateById(Stock record);
void insert(Stock record);
void insertBatch(List<Stock> records);
int updateBatch(@Param("list") List<Long> ids, @Param("commodityCode") String commodityCode);
}

View File

@ -0,0 +1,134 @@
/*
* Copyright 1999-2021 Seata.io Group.
*
* 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
*
* http://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 mybatisflex.test.stockservice.service;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import javax.sql.DataSource;
import io.seata.spring.annotation.GlobalLock;
import io.seata.spring.annotation.GlobalTransactional;
import mybatisflex.test.stockservice.persistence.Stock;
import mybatisflex.test.stockservice.persistence.StockMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class StockService {
@Autowired
private StockMapper stockMapper;
@Autowired
private DataSource dataSource;
public void deduct(String commodityCode, int count) {
//There is a latent isolation problem here.
//I hope that users can solve it and deepen their understanding of seata isolation.
//At the bottom I will put a reference solution.
Stock stock = stockMapper.findByCommodityCode(commodityCode);
stock.setCount(stock.getCount() - count);
stockMapper.updateById(stock);
}
@GlobalLock
public Stock get(Integer id) {
return stockMapper.selectById(id);
}
/**
* 0.8.0 release
*
* @throws SQLException
*/
@GlobalTransactional
public void batchUpdate() throws SQLException {
Connection connection = null;
PreparedStatement preparedStatement = null;
try {
connection = dataSource.getConnection();
connection.setAutoCommit(false);
String sql = "update stock_tbl set count = ?" + " where id = ? and commodity_code = ?";
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1, 100);
preparedStatement.setLong(2, 1);
preparedStatement.setString(3, "2001");
preparedStatement.addBatch();
preparedStatement.setInt(1, 200);
preparedStatement.setLong(2, 2);
preparedStatement.setString(3, "2002");
preparedStatement.addBatch();
preparedStatement.setInt(1, 300);
preparedStatement.setLong(2, 3);
preparedStatement.setString(3, "2003");
preparedStatement.addBatch();
preparedStatement.executeBatch();
connection.commit();
System.out.println(1 / 0);
} catch (Exception e) {
throw e;
} finally {
connection.close();
preparedStatement.close();
}
}
/**
* 0.8.0 release
*
* @throws SQLException
*/
@GlobalTransactional
public void batchDelete() throws SQLException {
Connection connection = null;
PreparedStatement preparedStatement = null;
try {
connection = dataSource.getConnection();
connection.setAutoCommit(false);
String sql = "delete from stock_tbl where count = ? and commodity_code = ?";
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1, 11);
preparedStatement.setString(2, "2001");
preparedStatement.addBatch();
preparedStatement.setInt(1, 22);
preparedStatement.setString(2, "2002");
preparedStatement.addBatch();
preparedStatement.setInt(1, 33);
preparedStatement.setString(2, "2003");
preparedStatement.addBatch();
preparedStatement.executeBatch();
connection.commit();
System.out.println(1 / 0);
} catch (Exception e) {
throw e;
} finally {
connection.close();
preparedStatement.close();
}
}
}
/*
reference solution:
@Transactional
public void deduct(String commodityCode, int count) {
//select + for update
Stock stock = stockMapper.findByCommodityCode(commodityCode);
stock.setCount(stock.getCount() - count);
stockMapper.updateById(stock);
}
1.select for update,refer https://seata.io/zh-cn/docs/overview/faq.html#4
2.(optional)use @Transactional,keep X locks held until connection submission
*/

View File

@ -0,0 +1,129 @@
server:
port: 8081
mybatis-flex:
seata-config:
enable: true #启动seata
seata-mode: XA #xa或者ta
datasource:
stockdb:
url: jdbc:mysql://127.0.0.1:3306/db_stock
username: root
password: 131496
#spring:
# datasource:
# type: com.alibaba.druid.pool.DruidDataSource
# driver-class-name: com.mysql.jdbc.Driver
# url: jdbc:mysql://127.0.0.1:3306/db_stock?useSSL=false&serverTimezone=UTC
# username: root
# password: 131496
spring:
main:
allow-circular-references: true
seata:
enabled: true
application-id: stock-service
tx-service-group: my_test_tx_group
enable-auto-data-source-proxy: false
#use-jdk-proxy: false
client:
rm:
async-commit-buffer-limit: 1000
report-retry-count: 5
table-meta-check-enable: false
report-success-enable: false
lock:
retry-interval: 10
retry-times: 30
retry-policy-branch-rollback-on-conflict: true
tm:
commit-retry-count: 5
rollback-retry-count: 5
undo:
data-validation: true
log-serialization: jackson
log-table: undo_log
log:
exceptionRate: 100
service:
vgroup-mapping:
my_test_tx_group: default
grouplist:
default: 127.0.0.1:8091
#enable-degrade: false
#disable-global-transaction: false
transport:
shutdown:
wait: 3
thread-factory:
boss-thread-prefix: NettyBoss
worker-thread-prefix: NettyServerNIOWorker
server-executor-thread-prefix: NettyServerBizHandler
share-boss-worker: false
client-selector-thread-prefix: NettyClientSelector
client-selector-thread-size: 1
client-worker-thread-prefix: NettyClientWorkerThread
worker-thread-size: default
boss-thread-size: 1
type: TCP
server: NIO
heartbeat: true
serialization: seata
compressor: none
enable-client-batch-send-request: true
config:
type: file
consul:
server-addr: 127.0.0.1:8500
apollo:
apollo-meta: http://192.168.1.204:8801
app-id: seata-server
namespace: application
etcd3:
server-addr: http://localhost:2379
nacos:
namespace:
serverAddr: localhost
group: SEATA_GROUP
zk:
server-addr: 127.0.0.1:2181
session-timeout: 6000
connect-timeout: 2000
username: ""
password: ""
registry:
type: file
consul:
cluster: default
server-addr: 127.0.0.1:8500
etcd3:
cluster: default
serverAddr: http://localhost:2379
eureka:
application: default
weight: 1
service-url: http://localhost:8761/eureka
nacos:
cluster: default
server-addr: localhost
namespace:
redis:
server-addr: localhost:6379
db: 0
password:
cluster: default
timeout: 0
sofa:
server-addr: 127.0.0.1:9603
application: default
region: DEFAULT_ZONE
datacenter: DefaultDataCenter
cluster: default
group: SEATA_GROUP
addressWaitTime: 3000
zk:
cluster: default
server-addr: 127.0.0.1:2181
session-timeout: 6000
connect-timeout: 2000
username: ""
password: ""

View File

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="mybatisflex.test.stockservice.persistence.StockMapper">
<resultMap id="BaseResultMap" type="mybatisflex.test.stockservice.persistence.Stock">
<id column="id" property="id" jdbcType="INTEGER"/>
<result column="commodity_code" property="commodityCode" jdbcType="VARCHAR"/>
<result column="count" property="count" jdbcType="INTEGER"/>
</resultMap>
<select id="selectById" resultType="mybatisflex.test.stockservice.persistence.Stock">
select id, commodity_code, count
from stock_tbl
WHERE id = #{id}
</select>
<select id="findByCommodityCode" resultType="mybatisflex.test.stockservice.persistence.Stock">
select id, commodity_code commodityCode, count
from stock_tbl
WHERE commodity_code = #{commodityCode}
</select>
<update id="updateById">
update stock_tbl
set count = #{count,jdbcType=INTEGER}
WHERE id = #{id}
</update>
<insert id="insert" parameterType="mybatisflex.test.stockservice.persistence.Stock">
insert into stock_tbl (commodity_code, count)
values (#{commodityCode,jdbcType=VARCHAR}, #{count,jdbcType=INTEGER})
</insert>
<insert id="insertBatch" parameterType="mybatisflex.test.stockservice.persistence.Stock">
insert into stock_tbl (commodity_code, count)
values
<foreach collection="list" item="item" index="index" separator=",">
(#{item.commodityCode,jdbcType=VARCHAR}, #{item.count,jdbcType=INTEGER})
</foreach>
</insert>
<update id="updateBatch">
update stock_tbl set count = 100
WHERE id IN
<foreach collection="list" index="index" item="item" open="(" separator="," close=")">
#{item}
</foreach>
and commodity_code = #{commodityCode,jdbcType=VARCHAR}
</update>
</mapper>

View File

@ -25,7 +25,7 @@
<dependency> <dependency>
<groupId>com.mybatis-flex</groupId> <groupId>com.mybatis-flex</groupId>
<artifactId>mybatis-flex-codegen</artifactId> <artifactId>mybatis-flex-codegen</artifactId>
<version>1.5.6</version> <version>${mybatis-flex.version}</version>
</dependency> </dependency>
<dependency> <dependency>

View File

@ -19,6 +19,7 @@
<module>mybatis-flex-spring-boot-test</module> <module>mybatis-flex-spring-boot-test</module>
<module>mybatis-flex-spring-cloud-test</module> <module>mybatis-flex-spring-cloud-test</module>
<module>mybatis-flex-spring-boot-seata</module> <module>mybatis-flex-spring-boot-seata</module>
<module>mybatis-flex-spring-boot-seata-demo</module>
</modules> </modules>
<properties> <properties>