Seata2_案例
1.Seata之Order-Module配置搭建
新建module:seata-order-service2001
下订单 -> 减库存 -> 扣余额 -> 改(订单)状态
seata-order-service2001
POM
<dependencies><!--nacos--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!--seata--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-seata</artifactId><exclusions><exclusion><artifactId>seata-all</artifactId><groupId>io.seata</groupId></exclusion></exclusions></dependency><dependency><groupId>io.seata</groupId><artifactId>seata-all</artifactId><version>1.4.2</version></dependency><!--feign--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><!--web-actuator--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><!--mysql-druid--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency></dependencies>
配置文件 yml
server:port: 2001spring:application:name: seata-order-servicecloud:alibaba:seata:#自定义事务组名称需要与seata-server中的对应tx-service-group: fsp_tx_groupnacos:discovery:server-addr: localhost:8848datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/seata_orderusername: rootpassword: 123456feign:hystrix:enabled: falselogging:level:io:seata: infomybatis:mapperLocations: classpath:mapper/*.xml
domain
@Data@AllArgsConstructor@NoArgsConstructorpublic class Order{private Long id;private Long userId;private Long productId;private Integer count;private BigDecimal money;private Integer status; //订单状态:0:创建中;1:已完结}
2.Seata之Order-Module撸码(上)
Dao接口及实现
@Mapperpublic interface OrderDao {//1 新建订单void create(Order order);//2 修改订单状态,从零改为1void update(@Param("userId") Long userId, @Param("status") Integer status);}
OrderDao.xml
<?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="com.zds.egg.dao.OrderDao"><resultMap id="BaseResultMap" type="ccom.zds.egg.dao.domain.Order"><id column="id" property="id" jdbcType="BIGINT"/><result column="user_id" property="userId" jdbcType="BIGINT"/><result column="product_id" property="productId" jdbcType="BIGINT"/><result column="count" property="count" jdbcType="INTEGER"/><result column="money" property="money" jdbcType="DECIMAL"/><result column="status" property="status" jdbcType="INTEGER"/></resultMap><insert id="create">insert into t_order (id,user_id,product_id,count,money,status)values (null,#{userId},#{productId},#{count},#{money},0);</insert><update id="update">update t_order set status = 1where user_id=#{userId} and status = #{status};</update></mapper>
Service接口及实现
- OrderService
- OrderServiceImpl
- StorageService
AccountService
public interface OrderService {void create(Order order);}
@FeignClient(value = "seata-account-service")public interface AccountService {@PostMapping(value = "/account/decrease")SingleResult decrease(@RequestParam("userId") Long userId, @RequestParam("money") BigDecimal money);}
@FeignClient(value = "seata-storage-service")public interface StorageService {@PostMapping(value = "/storage/decrease")SingleResult decrease(@RequestParam("productId") Long productId, @RequestParam("count") Integer count);}
@Service@Slf4jpublic class OrderServiceImpl implements OrderService {@Resourceprivate OrderDao orderDao;@Resourceprivate StorageService storageService;@Resourceprivate AccountService accountService;@Overridepublic void create(Order order) {log.info("----->开始新建订单");//1 新建订单orderDao.create(order);//2 扣减库存log.info("----->订单微服务开始调用库存,做扣减Count");storageService.decrease(order.getProductId(),order.getCount());log.info("----->订单微服务开始调用库存,做扣减end");//3 扣减账户log.info("----->订单微服务开始调用账户,做扣减Money");accountService.decrease(order.getUserId(),order.getMoney());log.info("----->订单微服务开始调用账户,做扣减end");//4 修改订单状态,从零到1,1代表已经完成log.info("----->修改订单状态开始");orderDao.update(order.getUserId(),0);log.info("----->修改订单状态结束");log.info("----->下订单结束了,O(∩_∩)O哈哈~");}}
3.Seata之Order-Module撸码(下)
Controller
@RestControllerpublic class OrderController{@Resourceprivate OrderService orderService;@GetMapping("/order/create")public SingleResult create(Order order){orderService.create(order);return new SingleResult().success("","订单创建成功");}}
Config配置
MyBatisConfig
- DataSourceProxyConfig
import org.mybatis.spring.annotation.MapperScan;import org.springframework.context.annotation.Configuration;@Configuration@MapperScan({"com.zds.egg.dao"})public class MyBatisConfig {}
主启动import com.alibaba.druid.pool.DruidDataSource;import io.seata.rm.datasource.DataSourceProxy;import org.apache.ibatis.session.SqlSessionFactory;import org.mybatis.spring.SqlSessionFactoryBean;import org.mybatis.spring.transaction.SpringManagedTransactionFactory;import org.springframework.beans.factory.annotation.Value;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.core.io.support.PathMatchingResourcePatternResolver;import javax.sql.DataSource;/*** 使用Seata对数据源进行代理*/@Configurationpublic class DataSourceProxyConfig {@Value("${mybatis.mapperLocations}")private String mapperLocations;@Bean@ConfigurationProperties(prefix = "spring.datasource")public DataSource druidDataSource(){return new DruidDataSource();}@Beanpublic DataSourceProxy dataSourceProxy(DataSource dataSource) {return new DataSourceProxy(dataSource);}@Beanpublic SqlSessionFactory sqlSessionFactoryBean(DataSourceProxy dataSourceProxy) throws Exception {SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();sqlSessionFactoryBean.setDataSource(dataSourceProxy);sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mapperLocations));sqlSessionFactoryBean.setTransactionFactory(new SpringManagedTransactionFactory());return sqlSessionFactoryBean.getObject();}}
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;import org.springframework.cloud.openfeign.EnableFeignClients;@EnableDiscoveryClient@EnableFeignClients//取消数据源的自动创建,而是使用自己定义的@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)public class SeataOrderMainApp2001{public static void main(String[] args){SpringApplication.run(SeataOrderMainApp2001.class, args);}}
4.Seata之Storage-Module说明
5.Seata之Account-Module说明
6.Seata之@GlobalTransactional验证
7.Seata之原理简介
