mirror of
https://gitee.com/mybatis-flex/mybatis-flex.git
synced 2025-12-06 16:48:24 +08:00
新增seata官方演示demo替换成spring-flex结合演示
This commit is contained in:
parent
d654d10ac8
commit
e0f287fffd
@ -88,6 +88,6 @@ public class FlexSpringTransaction implements Transaction {
|
||||
|
||||
@Override
|
||||
public Integer getTimeout() throws SQLException {
|
||||
return getConnection().getNetworkTimeout();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
|
||||
}
|
||||
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -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: ""
|
||||
@ -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>
|
||||
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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: ""
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -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() {
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
|
||||
}
|
||||
@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
@ -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: ""
|
||||
@ -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>
|
||||
@ -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;
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
@ -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
|
||||
*/
|
||||
@ -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: ""
|
||||
@ -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>
|
||||
@ -25,7 +25,7 @@
|
||||
<dependency>
|
||||
<groupId>com.mybatis-flex</groupId>
|
||||
<artifactId>mybatis-flex-codegen</artifactId>
|
||||
<version>1.5.6</version>
|
||||
<version>${mybatis-flex.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
<module>mybatis-flex-spring-boot-test</module>
|
||||
<module>mybatis-flex-spring-cloud-test</module>
|
||||
<module>mybatis-flex-spring-boot-seata</module>
|
||||
<module>mybatis-flex-spring-boot-seata-demo</module>
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user