diff --git a/README.md b/README.md
index cd5ae8676..458d80e93 100644
--- a/README.md
+++ b/README.md
@@ -18,3 +18,4 @@ Samples for Fescar. This project contains several sub-projects, each of which is
* [nacos](https://github.com/fescar-group/fescar-samples/tree/master/nacos) - Integration example of [Fescar](https://github.com/alibaba/fescar)、 [Apache Dubbo](https://github.com/apache/incubator-dubbo) and [Alibaba Nacos](https://github.com/alibaba/nacos/)
* [springboot-dubbo-fescar](https://github.com/fescar-group/fescar-samples/tree/master/nutzboot-dubbo-fescar) - Integration example of [Fescar](https://github.com/alibaba/fescar)、 [Apache Dubbo](https://github.com/apache/incubator-dubbo) and [Spring Boot](https://github.com/spring-projects/spring-boot/)
* [nutzboot-dubbo-fescar](https://github.com/fescar-group/fescar-samples/tree/master/nutzboot-dubbo-fescar) - Integration example of [Fescar](https://github.com/alibaba/fescar)、 [Apache Dubbo](https://github.com/apache/incubator-dubbo) and [NutzBoot](https://github.com/nutzam/nutzboot/)
+* [springcloud-jpa-seata](https://github.com/fescar-group/fescar-samples/tree/master/springcloud-jpa-seata) - Integration example of [Seata](https://github.com/Seata) and [Spring Cloud](https://github.com/spring-cloud)
diff --git a/pom.xml b/pom.xml
index 1907eb542..a01b2034d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -61,7 +61,7 @@
nacos
springboot-dubbo-fescar
tcc
-
+ springcloud-jpa-seata
diff --git a/springcloud-jpa-seata/README.md b/springcloud-jpa-seata/README.md
new file mode 100644
index 000000000..82ee46638
--- /dev/null
+++ b/springcloud-jpa-seata/README.md
@@ -0,0 +1,27 @@
+# seata-sample
+基于spring cloud+feign+spring jpa+spring cloud alibaba fescar+mysql
+
+### 准备工作
+1. 执行sql/all_in_one.sql
+
+2. 下载[0.4.1](https://github.com/seata/seata/releases/tag/v0.4.1)版本server
+
+ 客户端与服务端版本号保持一致
+3. 启动fescar server
+
+ sh fescar-server.sh 8091 ../data/
+4. 启动business、storage、account、order
+
+ 数据库默认连接127.0.0.1:3306,不同的注意修改
+
+5. 事务成功 GET http://127.0.0.1:8084/purchase/commit
+
+6. 事务回滚 GET http://127.0.0.1:8084/purchase/rollback
+
+### 验证数据
+1. 事务成功
+
+ 库存减1、订单加1、余额减5
+2. 事务回滚
+
+ 数据无变化
\ No newline at end of file
diff --git a/springcloud-jpa-seata/business-service/pom.xml b/springcloud-jpa-seata/business-service/pom.xml
new file mode 100755
index 000000000..28997776f
--- /dev/null
+++ b/springcloud-jpa-seata/business-service/pom.xml
@@ -0,0 +1,50 @@
+
+
+
+ com.alibaba.fescar
+ springcloud-jpa-seata
+ 1.0.0-SNAPSHOT
+
+ 4.0.0
+
+ business-service
+ jar
+
+ business-service
+ Demo project for Spring Boot
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ org.springframework.cloud
+ spring-cloud-starter-openfeign
+
+
+ org.springframework.cloud
+ spring-cloud-alibaba-fescar
+
+
+ com.alibaba.fescar
+ fescar-spring
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/springcloud-jpa-seata/business-service/src/main/java/com/alibaba/seata/sample/BusinessApplication.java b/springcloud-jpa-seata/business-service/src/main/java/com/alibaba/seata/sample/BusinessApplication.java
new file mode 100755
index 000000000..066f3ec4f
--- /dev/null
+++ b/springcloud-jpa-seata/business-service/src/main/java/com/alibaba/seata/sample/BusinessApplication.java
@@ -0,0 +1,15 @@
+package com.alibaba.seata.sample;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.openfeign.EnableFeignClients;
+
+@SpringBootApplication
+@EnableFeignClients
+public class BusinessApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(BusinessApplication.class, args);
+ }
+
+}
diff --git a/springcloud-jpa-seata/business-service/src/main/java/com/alibaba/seata/sample/controller/BusinessController.java b/springcloud-jpa-seata/business-service/src/main/java/com/alibaba/seata/sample/controller/BusinessController.java
new file mode 100755
index 000000000..90016b8a6
--- /dev/null
+++ b/springcloud-jpa-seata/business-service/src/main/java/com/alibaba/seata/sample/controller/BusinessController.java
@@ -0,0 +1,39 @@
+package com.alibaba.seata.sample.controller;
+
+import com.alibaba.seata.sample.service.BusinessService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+public class BusinessController {
+
+ @Autowired
+ private BusinessService businessService;
+
+ /**
+ * 购买下单,模拟全局事务提交
+ * @return
+ */
+ @RequestMapping("/purchase/commit")
+ public Boolean purchaseCommit(){
+ 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;
+ }
+}
diff --git a/springcloud-jpa-seata/business-service/src/main/java/com/alibaba/seata/sample/feign/OrderFeignClient.java b/springcloud-jpa-seata/business-service/src/main/java/com/alibaba/seata/sample/feign/OrderFeignClient.java
new file mode 100644
index 000000000..ce0766910
--- /dev/null
+++ b/springcloud-jpa-seata/business-service/src/main/java/com/alibaba/seata/sample/feign/OrderFeignClient.java
@@ -0,0 +1,22 @@
+package com.alibaba.seata.sample.feign;
+
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestParam;
+
+/**
+ * Description:
+ *
+ * @author fangliangsheng
+ * @date 2019-04-04
+ */
+@FeignClient(name = "order-service", url = "127.0.0.1:8082")
+public interface OrderFeignClient {
+
+ @GetMapping("/create")
+ void create(@RequestParam("userId") String userId,
+ @RequestParam("commodityCode") String commodityCode,
+ @RequestParam("count") Integer count);
+
+}
diff --git a/springcloud-jpa-seata/business-service/src/main/java/com/alibaba/seata/sample/feign/StorageFeignClient.java b/springcloud-jpa-seata/business-service/src/main/java/com/alibaba/seata/sample/feign/StorageFeignClient.java
new file mode 100644
index 000000000..25b21e51d
--- /dev/null
+++ b/springcloud-jpa-seata/business-service/src/main/java/com/alibaba/seata/sample/feign/StorageFeignClient.java
@@ -0,0 +1,21 @@
+package com.alibaba.seata.sample.feign;
+
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestParam;
+
+/**
+ * Description:
+ *
+ * @author fangliangsheng
+ * @date 2019-04-04
+ */
+@FeignClient(name ="storage-service", url = "127.0.0.1:8081")
+public interface StorageFeignClient {
+
+ @GetMapping("/deduct")
+ void deduct(@RequestParam("commodityCode") String commodityCode,
+ @RequestParam("count") Integer count);
+
+}
diff --git a/springcloud-jpa-seata/business-service/src/main/java/com/alibaba/seata/sample/service/BusinessService.java b/springcloud-jpa-seata/business-service/src/main/java/com/alibaba/seata/sample/service/BusinessService.java
new file mode 100644
index 000000000..bacecd59a
--- /dev/null
+++ b/springcloud-jpa-seata/business-service/src/main/java/com/alibaba/seata/sample/service/BusinessService.java
@@ -0,0 +1,35 @@
+package com.alibaba.seata.sample.service;
+
+import com.alibaba.fescar.spring.annotation.GlobalTransactional;
+import com.alibaba.seata.sample.feign.OrderFeignClient;
+import com.alibaba.seata.sample.feign.StorageFeignClient;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * Description:
+ *
+ * @author fangliangsheng
+ * @date 2019-04-05
+ */
+@Service
+public class BusinessService {
+
+ @Autowired
+ private StorageFeignClient storageFeignClient;
+ @Autowired
+ private OrderFeignClient orderFeignClient;
+
+ /**
+ * 减库存,下订单
+ * @param userId
+ * @param commodityCode
+ * @param orderCount
+ */
+ @GlobalTransactional
+ public void purchase(String userId, String commodityCode, int orderCount){
+ storageFeignClient.deduct(commodityCode, orderCount);
+
+ orderFeignClient.create(userId, commodityCode, orderCount);
+ }
+}
diff --git a/springcloud-jpa-seata/business-service/src/main/resources/application.properties b/springcloud-jpa-seata/business-service/src/main/resources/application.properties
new file mode 100755
index 000000000..b561df4e1
--- /dev/null
+++ b/springcloud-jpa-seata/business-service/src/main/resources/application.properties
@@ -0,0 +1,5 @@
+spring.application.name=business-service
+server.port=8084
+
+logging.level.com.alibaba.fescar=debug
+spring.cloud.alibaba.fescar.tx-service-group=my_test_tx_group
\ No newline at end of file
diff --git a/springcloud-jpa-seata/business-service/src/main/resources/file.conf b/springcloud-jpa-seata/business-service/src/main/resources/file.conf
new file mode 100644
index 000000000..60e5d2557
--- /dev/null
+++ b/springcloud-jpa-seata/business-service/src/main/resources/file.conf
@@ -0,0 +1,41 @@
+transport {
+ # tcp udt unix-domain-socket
+ type = "TCP"
+ #NIO NATIVE
+ server = "NIO"
+ #enable heartbeat
+ heartbeat = true
+ #thread factory for netty
+ 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"
+ # netty boss thread size,will not be used for UDT
+ boss-thread-size = 1
+ #auto default pin or 8
+ worker-thread-size = 8
+ }
+}
+service {
+ #vgroup->rgroup
+ vgroup_mapping.my_test_tx_group = "default"
+ #only support single node
+ default.grouplist = "127.0.0.1:8091"
+ #degrade current not support
+ enableDegrade = false
+ #disable
+ disable = false
+ disableGlobalTransaction = false
+}
+
+client {
+ async.commit.buffer.limit = 10000
+ lock {
+ retry.internal = 10
+ retry.times = 30
+ }
+}
diff --git a/springcloud-jpa-seata/business-service/src/main/resources/registry.conf b/springcloud-jpa-seata/business-service/src/main/resources/registry.conf
new file mode 100644
index 000000000..3b926a282
--- /dev/null
+++ b/springcloud-jpa-seata/business-service/src/main/resources/registry.conf
@@ -0,0 +1,51 @@
+registry {
+ # file 、nacos 、eureka、redis、zk
+ type = "file"
+
+ nacos {
+ serverAddr = "localhost"
+ namespace = "public"
+ cluster = "default"
+ }
+ eureka {
+ serviceUrl = "http://localhost:1001/eureka"
+ application = "default"
+ weight = "1"
+ }
+ redis {
+ serverAddr = "localhost:6381"
+ db = "0"
+ }
+ zk {
+ cluster = "default"
+ serverAddr = "127.0.0.1:2181"
+ session.timeout = 6000
+ connect.timeout = 2000
+ }
+ file {
+ name = "file.conf"
+ }
+}
+
+config {
+ # file、nacos 、apollo、zk
+ type = "file"
+
+ nacos {
+ serverAddr = "localhost"
+ namespace = "public"
+ cluster = "default"
+ }
+ apollo {
+ app.id = "fescar-server"
+ apollo.meta = "http://192.168.1.204:8801"
+ }
+ zk {
+ serverAddr = "127.0.0.1:2181"
+ session.timeout = 6000
+ connect.timeout = 2000
+ }
+ file {
+ name = "file.conf"
+ }
+}
\ No newline at end of file
diff --git a/springcloud-jpa-seata/order-service/pom.xml b/springcloud-jpa-seata/order-service/pom.xml
new file mode 100755
index 000000000..6e22330bf
--- /dev/null
+++ b/springcloud-jpa-seata/order-service/pom.xml
@@ -0,0 +1,67 @@
+
+
+
+ com.alibaba.fescar
+ springcloud-jpa-seata
+ 1.0.0-SNAPSHOT
+
+ 4.0.0
+
+ order-service
+ jar
+
+ order-service
+ Demo project for Spring Boot
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ mysql
+ mysql-connector-java
+ runtime
+
+
+ com.alibaba
+ druid-spring-boot-starter
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+ org.springframework.cloud
+ spring-cloud-starter-openfeign
+
+
+ org.springframework.cloud
+ spring-cloud-starter-netflix-ribbon
+
+
+ org.springframework.cloud
+ spring-cloud-alibaba-fescar
+
+
+ com.alibaba.fescar
+ fescar-spring
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/springcloud-jpa-seata/order-service/src/main/java/com/alibaba/seata/sample/OrderApplication.java b/springcloud-jpa-seata/order-service/src/main/java/com/alibaba/seata/sample/OrderApplication.java
new file mode 100644
index 000000000..1a77d5281
--- /dev/null
+++ b/springcloud-jpa-seata/order-service/src/main/java/com/alibaba/seata/sample/OrderApplication.java
@@ -0,0 +1,35 @@
+package com.alibaba.seata.sample;
+
+import com.alibaba.druid.pool.DruidDataSource;
+import com.alibaba.fescar.rm.datasource.DataSourceProxy;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.cloud.openfeign.EnableFeignClients;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Primary;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+
+@SpringBootApplication
+@EnableFeignClients
+@EnableJpaRepositories
+public class OrderApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(OrderApplication.class, args);
+ }
+
+ @Bean
+ @ConfigurationProperties(prefix = "spring.datasource")
+ public DruidDataSource druidDataSource() {
+ DruidDataSource druidDataSource = new DruidDataSource();
+ return druidDataSource;
+ }
+
+ @Primary
+ @Bean("dataSource")
+ public DataSourceProxy dataSource(DruidDataSource druidDataSource) {
+ return new DataSourceProxy(druidDataSource);
+ }
+
+}
diff --git a/springcloud-jpa-seata/order-service/src/main/java/com/alibaba/seata/sample/controller/OrderController.java b/springcloud-jpa-seata/order-service/src/main/java/com/alibaba/seata/sample/controller/OrderController.java
new file mode 100644
index 000000000..64b54d7a2
--- /dev/null
+++ b/springcloud-jpa-seata/order-service/src/main/java/com/alibaba/seata/sample/controller/OrderController.java
@@ -0,0 +1,27 @@
+package com.alibaba.seata.sample.controller;
+
+import com.alibaba.seata.sample.service.OrderService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * Description:
+ *
+ * @author fangliangsheng
+ * @date 2019-04-04
+ */
+@RestController
+public class OrderController {
+
+ @Autowired
+ private OrderService orderService;
+
+ @GetMapping("/create")
+ public Boolean create(String userId,String commodityCode, Integer count){
+
+ orderService.create(userId, commodityCode, count);
+ return true;
+ }
+
+}
diff --git a/springcloud-jpa-seata/order-service/src/main/java/com/alibaba/seata/sample/entity/Order.java b/springcloud-jpa-seata/order-service/src/main/java/com/alibaba/seata/sample/entity/Order.java
new file mode 100644
index 000000000..4341afd15
--- /dev/null
+++ b/springcloud-jpa-seata/order-service/src/main/java/com/alibaba/seata/sample/entity/Order.java
@@ -0,0 +1,62 @@
+package com.alibaba.seata.sample.entity;
+
+import org.hibernate.annotations.DynamicInsert;
+import org.hibernate.annotations.DynamicUpdate;
+
+import javax.persistence.*;
+import java.math.BigDecimal;
+
+@Entity
+@Table(name = "order_tbl")
+@DynamicUpdate
+@DynamicInsert
+public class Order {
+
+ @Id
+ @GeneratedValue(strategy = GenerationType.IDENTITY)
+ private Long id;
+ private String userId;
+ private String commodityCode;
+ private BigDecimal money;
+ private Integer count;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long 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 BigDecimal getMoney() {
+ return money;
+ }
+
+ public void setMoney(BigDecimal money) {
+ this.money = money;
+ }
+
+ public Integer getCount() {
+ return count;
+ }
+
+ public void setCount(Integer count) {
+ this.count = count;
+ }
+}
diff --git a/springcloud-jpa-seata/order-service/src/main/java/com/alibaba/seata/sample/feign/UserFeignClient.java b/springcloud-jpa-seata/order-service/src/main/java/com/alibaba/seata/sample/feign/UserFeignClient.java
new file mode 100644
index 000000000..05eeb7b0a
--- /dev/null
+++ b/springcloud-jpa-seata/order-service/src/main/java/com/alibaba/seata/sample/feign/UserFeignClient.java
@@ -0,0 +1,21 @@
+package com.alibaba.seata.sample.feign;
+
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import java.math.BigDecimal;
+
+/**
+ * Description:
+ *
+ * @author fangliangsheng
+ * @date 2019-04-04
+ */
+@FeignClient(name = "user-service",url = "127.0.0.1:8083")
+public interface UserFeignClient {
+
+ @GetMapping("/debit")
+ Boolean debit(@RequestParam("userId") String userId,@RequestParam("money") BigDecimal money);
+}
diff --git a/springcloud-jpa-seata/order-service/src/main/java/com/alibaba/seata/sample/repository/OrderDAO.java b/springcloud-jpa-seata/order-service/src/main/java/com/alibaba/seata/sample/repository/OrderDAO.java
new file mode 100644
index 000000000..681164a86
--- /dev/null
+++ b/springcloud-jpa-seata/order-service/src/main/java/com/alibaba/seata/sample/repository/OrderDAO.java
@@ -0,0 +1,14 @@
+package com.alibaba.seata.sample.repository;
+
+import com.alibaba.seata.sample.entity.Order;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+/**
+ * Description:
+ *
+ * @author fangliangsheng
+ * @date 2019-04-04
+ */
+public interface OrderDAO extends JpaRepository {
+
+}
diff --git a/springcloud-jpa-seata/order-service/src/main/java/com/alibaba/seata/sample/service/OrderService.java b/springcloud-jpa-seata/order-service/src/main/java/com/alibaba/seata/sample/service/OrderService.java
new file mode 100644
index 000000000..9125157e4
--- /dev/null
+++ b/springcloud-jpa-seata/order-service/src/main/java/com/alibaba/seata/sample/service/OrderService.java
@@ -0,0 +1,42 @@
+package com.alibaba.seata.sample.service;
+
+import com.alibaba.seata.sample.repository.OrderDAO;
+import com.alibaba.seata.sample.feign.UserFeignClient;
+import com.alibaba.seata.sample.entity.Order;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.math.BigDecimal;
+
+/**
+ * Description:
+ *
+ * @author fangliangsheng
+ * @date 2019-04-04
+ */
+@Service
+public class OrderService {
+
+ @Autowired
+ private UserFeignClient userFeignClient;
+ @Autowired
+ private OrderDAO orderDAO;
+
+ @Transactional
+ 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);
+
+ orderDAO.save(order);
+
+ userFeignClient.debit(userId, orderMoney);
+ }
+
+}
diff --git a/springcloud-jpa-seata/order-service/src/main/resources/application.properties b/springcloud-jpa-seata/order-service/src/main/resources/application.properties
new file mode 100644
index 000000000..4a6d70143
--- /dev/null
+++ b/springcloud-jpa-seata/order-service/src/main/resources/application.properties
@@ -0,0 +1,12 @@
+spring.application.name=order-service
+server.port=8082
+
+spring.datasource.url=jdbc:mysql://127.0.0.1:3306/db_order?useSSL=false
+spring.datasource.username=root
+spring.datasource.password=
+spring.jpa.show-sql: true
+spring.jpa.format-sql: true
+
+spring.cloud.alibaba.fescar.tx-service-group=my_test_tx_group
+logging.level.org.springframework.cloud.alibaba.fescar.web=debug
+logging.level.com.alibaba.fescar=debug
\ No newline at end of file
diff --git a/springcloud-jpa-seata/order-service/src/main/resources/file.conf b/springcloud-jpa-seata/order-service/src/main/resources/file.conf
new file mode 100644
index 000000000..60e5d2557
--- /dev/null
+++ b/springcloud-jpa-seata/order-service/src/main/resources/file.conf
@@ -0,0 +1,41 @@
+transport {
+ # tcp udt unix-domain-socket
+ type = "TCP"
+ #NIO NATIVE
+ server = "NIO"
+ #enable heartbeat
+ heartbeat = true
+ #thread factory for netty
+ 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"
+ # netty boss thread size,will not be used for UDT
+ boss-thread-size = 1
+ #auto default pin or 8
+ worker-thread-size = 8
+ }
+}
+service {
+ #vgroup->rgroup
+ vgroup_mapping.my_test_tx_group = "default"
+ #only support single node
+ default.grouplist = "127.0.0.1:8091"
+ #degrade current not support
+ enableDegrade = false
+ #disable
+ disable = false
+ disableGlobalTransaction = false
+}
+
+client {
+ async.commit.buffer.limit = 10000
+ lock {
+ retry.internal = 10
+ retry.times = 30
+ }
+}
diff --git a/springcloud-jpa-seata/order-service/src/main/resources/registry.conf b/springcloud-jpa-seata/order-service/src/main/resources/registry.conf
new file mode 100644
index 000000000..3b926a282
--- /dev/null
+++ b/springcloud-jpa-seata/order-service/src/main/resources/registry.conf
@@ -0,0 +1,51 @@
+registry {
+ # file 、nacos 、eureka、redis、zk
+ type = "file"
+
+ nacos {
+ serverAddr = "localhost"
+ namespace = "public"
+ cluster = "default"
+ }
+ eureka {
+ serviceUrl = "http://localhost:1001/eureka"
+ application = "default"
+ weight = "1"
+ }
+ redis {
+ serverAddr = "localhost:6381"
+ db = "0"
+ }
+ zk {
+ cluster = "default"
+ serverAddr = "127.0.0.1:2181"
+ session.timeout = 6000
+ connect.timeout = 2000
+ }
+ file {
+ name = "file.conf"
+ }
+}
+
+config {
+ # file、nacos 、apollo、zk
+ type = "file"
+
+ nacos {
+ serverAddr = "localhost"
+ namespace = "public"
+ cluster = "default"
+ }
+ apollo {
+ app.id = "fescar-server"
+ apollo.meta = "http://192.168.1.204:8801"
+ }
+ zk {
+ serverAddr = "127.0.0.1:2181"
+ session.timeout = 6000
+ connect.timeout = 2000
+ }
+ file {
+ name = "file.conf"
+ }
+}
\ No newline at end of file
diff --git a/springcloud-jpa-seata/pom.xml b/springcloud-jpa-seata/pom.xml
new file mode 100755
index 000000000..b1985638f
--- /dev/null
+++ b/springcloud-jpa-seata/pom.xml
@@ -0,0 +1,101 @@
+
+
+ 4.0.0
+
+
+ com.alibaba.fescar
+ fescar-samples
+ 1.0.0-SNAPSHOT
+
+
+ springcloud-jpa-seata
+ com.alibaba.fescar
+ seata-sample
+ Demo project for Seata
+ pom
+
+
+ UTF-8
+ 1.8
+
+
+
+
+ user-service
+ order-service
+ storage-service
+ business-service
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ Finchley.BUILD-SNAPSHOT
+ pom
+ import
+
+
+ org.springframework.boot
+ spring-boot-dependencies
+ 2.0.0.RELEASE
+ pom
+ import
+
+
+ com.alibaba
+ druid-spring-boot-starter
+ 1.1.10
+
+
+ org.springframework.cloud
+ spring-cloud-alibaba-fescar
+ 2.1.0.BUILD-SNAPSHOT
+
+
+ com.alibaba.fescar
+ fescar-spring
+
+
+
+
+ com.alibaba.fescar
+ fescar-spring
+ 0.4.1
+
+
+ org.springframework
+ spring-context
+ 5.0.4.RELEASE
+
+
+ mysql
+ mysql-connector-java
+ 8.0.11
+
+
+
+
+
+
+ spring-snapshot
+ Spring Snapshot Repository
+ https://repo.spring.io/snapshot
+
+ true
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/springcloud-jpa-seata/sql/all_in_one.sql b/springcloud-jpa-seata/sql/all_in_one.sql
new file mode 100644
index 000000000..247cc1cdf
--- /dev/null
+++ b/springcloud-jpa-seata/sql/all_in_one.sql
@@ -0,0 +1,79 @@
+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,
+ `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=9 DEFAULT CHARSET=utf8;
+
+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 AUTO_INCREMENT=9 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,
+ `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=9 DEFAULT CHARSET=utf8;
+
+create schema db_storage;
+
+use db_storage;
+
+CREATE TABLE `storage_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 AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
+
+
+INSERT INTO storage_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,
+ `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=9 DEFAULT CHARSET=utf8;
\ No newline at end of file
diff --git a/springcloud-jpa-seata/storage-service/pom.xml b/springcloud-jpa-seata/storage-service/pom.xml
new file mode 100755
index 000000000..10da3ecf7
--- /dev/null
+++ b/springcloud-jpa-seata/storage-service/pom.xml
@@ -0,0 +1,63 @@
+
+
+
+ com.alibaba.fescar
+ springcloud-jpa-seata
+ 1.0.0-SNAPSHOT
+
+ 4.0.0
+
+ storage-service
+ jar
+
+ storage-service
+ Demo project for Spring Boot
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ mysql
+ mysql-connector-java
+ runtime
+
+
+ com.alibaba
+ druid-spring-boot-starter
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+ org.springframework.cloud
+ spring-cloud-starter-openfeign
+
+
+ org.springframework.cloud
+ spring-cloud-alibaba-fescar
+
+
+ com.alibaba.fescar
+ fescar-spring
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/springcloud-jpa-seata/storage-service/src/main/java/com/alibaba/seata/sample/StorageApplication.java b/springcloud-jpa-seata/storage-service/src/main/java/com/alibaba/seata/sample/StorageApplication.java
new file mode 100644
index 000000000..2949430c4
--- /dev/null
+++ b/springcloud-jpa-seata/storage-service/src/main/java/com/alibaba/seata/sample/StorageApplication.java
@@ -0,0 +1,33 @@
+package com.alibaba.seata.sample;
+
+import com.alibaba.druid.pool.DruidDataSource;
+import com.alibaba.fescar.rm.datasource.DataSourceProxy;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Primary;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+
+@SpringBootApplication
+@EnableJpaRepositories
+public class StorageApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(StorageApplication.class, args);
+ }
+
+ @Bean
+ @ConfigurationProperties(prefix = "spring.datasource")
+ public DruidDataSource druidDataSource() {
+ DruidDataSource druidDataSource = new DruidDataSource();
+ return druidDataSource;
+ }
+
+ @Primary
+ @Bean("dataSource")
+ public DataSourceProxy dataSource(DruidDataSource druidDataSource) {
+ return new DataSourceProxy(druidDataSource);
+ }
+
+}
diff --git a/springcloud-jpa-seata/storage-service/src/main/java/com/alibaba/seata/sample/controller/StorageController.java b/springcloud-jpa-seata/storage-service/src/main/java/com/alibaba/seata/sample/controller/StorageController.java
new file mode 100644
index 000000000..58e57c679
--- /dev/null
+++ b/springcloud-jpa-seata/storage-service/src/main/java/com/alibaba/seata/sample/controller/StorageController.java
@@ -0,0 +1,25 @@
+package com.alibaba.seata.sample.controller;
+
+import com.alibaba.seata.sample.service.StorageService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * Description:
+ *
+ * @author fangliangsheng
+ * @date 2019/3/28
+ */
+@RestController
+public class StorageController {
+
+ @Autowired
+ private StorageService storageService;
+
+ @GetMapping(path = "/deduct")
+ public Boolean deduct(String commodityCode, Integer count){
+ storageService.deduct(commodityCode,count);
+ return true;
+ }
+}
diff --git a/springcloud-jpa-seata/storage-service/src/main/java/com/alibaba/seata/sample/entity/Storage.java b/springcloud-jpa-seata/storage-service/src/main/java/com/alibaba/seata/sample/entity/Storage.java
new file mode 100644
index 000000000..aa3f3f4b5
--- /dev/null
+++ b/springcloud-jpa-seata/storage-service/src/main/java/com/alibaba/seata/sample/entity/Storage.java
@@ -0,0 +1,44 @@
+package com.alibaba.seata.sample.entity;
+
+import org.hibernate.annotations.DynamicInsert;
+import org.hibernate.annotations.DynamicUpdate;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+
+@Entity
+@Table(name = "storage_tbl")
+@DynamicUpdate
+@DynamicInsert
+public class Storage {
+
+ @Id
+ private Long id;
+ private String commodityCode;
+ private Integer count;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long 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;
+ }
+}
diff --git a/springcloud-jpa-seata/storage-service/src/main/java/com/alibaba/seata/sample/repository/StorageDAO.java b/springcloud-jpa-seata/storage-service/src/main/java/com/alibaba/seata/sample/repository/StorageDAO.java
new file mode 100644
index 000000000..a0186a3e6
--- /dev/null
+++ b/springcloud-jpa-seata/storage-service/src/main/java/com/alibaba/seata/sample/repository/StorageDAO.java
@@ -0,0 +1,16 @@
+package com.alibaba.seata.sample.repository;
+
+import com.alibaba.seata.sample.entity.Storage;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+/**
+ * Description:
+ *
+ * @author fangliangsheng
+ * @date 2019-04-04
+ */
+public interface StorageDAO extends JpaRepository {
+
+ Storage findByCommodityCode(String commodityCode);
+
+}
diff --git a/springcloud-jpa-seata/storage-service/src/main/java/com/alibaba/seata/sample/service/StorageService.java b/springcloud-jpa-seata/storage-service/src/main/java/com/alibaba/seata/sample/service/StorageService.java
new file mode 100644
index 000000000..5e9bb533a
--- /dev/null
+++ b/springcloud-jpa-seata/storage-service/src/main/java/com/alibaba/seata/sample/service/StorageService.java
@@ -0,0 +1,28 @@
+package com.alibaba.seata.sample.service;
+
+import com.alibaba.seata.sample.entity.Storage;
+import com.alibaba.seata.sample.repository.StorageDAO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * Description:
+ *
+ * @author fangliangsheng
+ * @date 2019-04-04
+ */
+@Service
+public class StorageService {
+
+ @Autowired
+ private StorageDAO storageDAO;
+
+ @Transactional
+ public void deduct(String commodityCode, int count){
+ Storage storage = storageDAO.findByCommodityCode(commodityCode);
+ storage.setCount(storage.getCount()-count);
+
+ storageDAO.save(storage);
+ }
+}
diff --git a/springcloud-jpa-seata/storage-service/src/main/resources/application.properties b/springcloud-jpa-seata/storage-service/src/main/resources/application.properties
new file mode 100644
index 000000000..19deaf490
--- /dev/null
+++ b/springcloud-jpa-seata/storage-service/src/main/resources/application.properties
@@ -0,0 +1,12 @@
+spring.application.name=storage-service
+server.port=8081
+
+spring.datasource.url=jdbc:mysql://127.0.0.1:3306/db_storage?useSSL=false
+spring.datasource.username=root
+spring.datasource.password=
+spring.jpa.show-sql: true
+spring.jpa.format-sql: true
+
+spring.cloud.alibaba.fescar.tx-service-group=my_test_tx_group
+logging.level.org.springframework.cloud.alibaba.fescar.web=debug
+logging.level.com.alibaba.fescar=debug
\ No newline at end of file
diff --git a/springcloud-jpa-seata/storage-service/src/main/resources/file.conf b/springcloud-jpa-seata/storage-service/src/main/resources/file.conf
new file mode 100644
index 000000000..60e5d2557
--- /dev/null
+++ b/springcloud-jpa-seata/storage-service/src/main/resources/file.conf
@@ -0,0 +1,41 @@
+transport {
+ # tcp udt unix-domain-socket
+ type = "TCP"
+ #NIO NATIVE
+ server = "NIO"
+ #enable heartbeat
+ heartbeat = true
+ #thread factory for netty
+ 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"
+ # netty boss thread size,will not be used for UDT
+ boss-thread-size = 1
+ #auto default pin or 8
+ worker-thread-size = 8
+ }
+}
+service {
+ #vgroup->rgroup
+ vgroup_mapping.my_test_tx_group = "default"
+ #only support single node
+ default.grouplist = "127.0.0.1:8091"
+ #degrade current not support
+ enableDegrade = false
+ #disable
+ disable = false
+ disableGlobalTransaction = false
+}
+
+client {
+ async.commit.buffer.limit = 10000
+ lock {
+ retry.internal = 10
+ retry.times = 30
+ }
+}
diff --git a/springcloud-jpa-seata/storage-service/src/main/resources/registry.conf b/springcloud-jpa-seata/storage-service/src/main/resources/registry.conf
new file mode 100644
index 000000000..3b926a282
--- /dev/null
+++ b/springcloud-jpa-seata/storage-service/src/main/resources/registry.conf
@@ -0,0 +1,51 @@
+registry {
+ # file 、nacos 、eureka、redis、zk
+ type = "file"
+
+ nacos {
+ serverAddr = "localhost"
+ namespace = "public"
+ cluster = "default"
+ }
+ eureka {
+ serviceUrl = "http://localhost:1001/eureka"
+ application = "default"
+ weight = "1"
+ }
+ redis {
+ serverAddr = "localhost:6381"
+ db = "0"
+ }
+ zk {
+ cluster = "default"
+ serverAddr = "127.0.0.1:2181"
+ session.timeout = 6000
+ connect.timeout = 2000
+ }
+ file {
+ name = "file.conf"
+ }
+}
+
+config {
+ # file、nacos 、apollo、zk
+ type = "file"
+
+ nacos {
+ serverAddr = "localhost"
+ namespace = "public"
+ cluster = "default"
+ }
+ apollo {
+ app.id = "fescar-server"
+ apollo.meta = "http://192.168.1.204:8801"
+ }
+ zk {
+ serverAddr = "127.0.0.1:2181"
+ session.timeout = 6000
+ connect.timeout = 2000
+ }
+ file {
+ name = "file.conf"
+ }
+}
\ No newline at end of file
diff --git a/springcloud-jpa-seata/user-service/pom.xml b/springcloud-jpa-seata/user-service/pom.xml
new file mode 100755
index 000000000..1b2fcfb7b
--- /dev/null
+++ b/springcloud-jpa-seata/user-service/pom.xml
@@ -0,0 +1,63 @@
+
+
+
+ com.alibaba.fescar
+ springcloud-jpa-seata
+ 1.0.0-SNAPSHOT
+
+ 4.0.0
+
+ user-service
+ jar
+
+ user-service
+ Demo project for Spring Boot
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+ test
+
+
+ mysql
+ mysql-connector-java
+ runtime
+
+
+ com.alibaba
+ druid-spring-boot-starter
+
+
+ org.springframework.boot
+ spring-boot-starter-data-jpa
+
+
+ org.springframework.cloud
+ spring-cloud-starter-openfeign
+
+
+ org.springframework.cloud
+ spring-cloud-alibaba-fescar
+
+
+ com.alibaba.fescar
+ fescar-spring
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+
+
+
diff --git a/springcloud-jpa-seata/user-service/src/main/java/com/alibaba/seata/sample/AccountApplication.java b/springcloud-jpa-seata/user-service/src/main/java/com/alibaba/seata/sample/AccountApplication.java
new file mode 100755
index 000000000..128f1ed90
--- /dev/null
+++ b/springcloud-jpa-seata/user-service/src/main/java/com/alibaba/seata/sample/AccountApplication.java
@@ -0,0 +1,34 @@
+package com.alibaba.seata.sample;
+
+import com.alibaba.druid.pool.DruidDataSource;
+import com.alibaba.fescar.rm.datasource.DataSourceProxy;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.cloud.openfeign.EnableFeignClients;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Primary;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+
+@SpringBootApplication
+@EnableFeignClients
+@EnableJpaRepositories
+public class AccountApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(AccountApplication.class, args);
+ }
+
+ @Bean
+ @ConfigurationProperties(prefix = "spring.datasource")
+ public DruidDataSource druidDataSource() {
+ DruidDataSource druidDataSource = new DruidDataSource();
+ return druidDataSource;
+ }
+
+ @Primary
+ @Bean("dataSource")
+ public DataSourceProxy dataSource(DruidDataSource druidDataSource) {
+ return new DataSourceProxy(druidDataSource);
+ }
+}
diff --git a/springcloud-jpa-seata/user-service/src/main/java/com/alibaba/seata/sample/controller/AccountController.java b/springcloud-jpa-seata/user-service/src/main/java/com/alibaba/seata/sample/controller/AccountController.java
new file mode 100755
index 000000000..514a1244e
--- /dev/null
+++ b/springcloud-jpa-seata/user-service/src/main/java/com/alibaba/seata/sample/controller/AccountController.java
@@ -0,0 +1,27 @@
+package com.alibaba.seata.sample.controller;
+
+import com.alibaba.seata.sample.service.AccountService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.math.BigDecimal;
+
+/**
+ * Description:
+ * @author fangliangsheng
+ * @date 2017/12/25
+ */
+@RestController
+public class AccountController {
+
+ @Autowired
+ private AccountService accountService;
+
+ @RequestMapping("/debit")
+ public Boolean debit(String userId, BigDecimal money){
+ accountService.debit(userId, money);
+
+ return true;
+ }
+}
diff --git a/springcloud-jpa-seata/user-service/src/main/java/com/alibaba/seata/sample/entity/Account.java b/springcloud-jpa-seata/user-service/src/main/java/com/alibaba/seata/sample/entity/Account.java
new file mode 100644
index 000000000..53954bcd7
--- /dev/null
+++ b/springcloud-jpa-seata/user-service/src/main/java/com/alibaba/seata/sample/entity/Account.java
@@ -0,0 +1,45 @@
+package com.alibaba.seata.sample.entity;
+
+import org.hibernate.annotations.DynamicInsert;
+import org.hibernate.annotations.DynamicUpdate;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import java.math.BigDecimal;
+
+@Entity
+@Table(name = "account_tbl")
+@DynamicUpdate
+@DynamicInsert
+public class Account {
+
+ @Id
+ private Long id;
+ private String userId;
+ private BigDecimal money;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long 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;
+ }
+}
diff --git a/springcloud-jpa-seata/user-service/src/main/java/com/alibaba/seata/sample/repository/AccountDAO.java b/springcloud-jpa-seata/user-service/src/main/java/com/alibaba/seata/sample/repository/AccountDAO.java
new file mode 100644
index 000000000..db9454054
--- /dev/null
+++ b/springcloud-jpa-seata/user-service/src/main/java/com/alibaba/seata/sample/repository/AccountDAO.java
@@ -0,0 +1,16 @@
+package com.alibaba.seata.sample.repository;
+
+import com.alibaba.seata.sample.entity.Account;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+/**
+ * Description:
+ *
+ * @author fangliangsheng
+ * @date 2019/3/28
+ */
+public interface AccountDAO extends JpaRepository {
+
+ Account findByUserId(String userId);
+
+}
diff --git a/springcloud-jpa-seata/user-service/src/main/java/com/alibaba/seata/sample/service/AccountService.java b/springcloud-jpa-seata/user-service/src/main/java/com/alibaba/seata/sample/service/AccountService.java
new file mode 100644
index 000000000..aea1ae01b
--- /dev/null
+++ b/springcloud-jpa-seata/user-service/src/main/java/com/alibaba/seata/sample/service/AccountService.java
@@ -0,0 +1,35 @@
+package com.alibaba.seata.sample.service;
+
+import com.alibaba.seata.sample.entity.Account;
+import com.alibaba.seata.sample.repository.AccountDAO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.math.BigDecimal;
+
+/**
+ * Description:
+ *
+ * @author fangliangsheng
+ * @date 2019-04-05
+ */
+@Service
+public class AccountService {
+
+ @Autowired
+ private AccountDAO accountDAO;
+
+ private static final String ERROR_USER_ID= "1002";
+
+ @Transactional(rollbackFor = Exception.class)
+ public void debit(String userId, BigDecimal num){
+ Account account = accountDAO.findByUserId(userId);
+ account.setMoney(account.getMoney().subtract(num));
+ accountDAO.save(account);
+
+ if (ERROR_USER_ID.equals(userId)){
+ throw new RuntimeException("account branch exception");
+ }
+ }
+}
diff --git a/springcloud-jpa-seata/user-service/src/main/resources/application.properties b/springcloud-jpa-seata/user-service/src/main/resources/application.properties
new file mode 100755
index 000000000..3ac2f7dac
--- /dev/null
+++ b/springcloud-jpa-seata/user-service/src/main/resources/application.properties
@@ -0,0 +1,11 @@
+spring.application.name=account-service
+server.port=8083
+
+spring.datasource.url=jdbc:mysql://127.0.0.1:3306/db_account?useSSL=false
+spring.datasource.username=root
+spring.datasource.password=
+spring.jpa.show-sql: true
+spring.jpa.format-sql: true
+
+logging.level.com.alibaba.fescar=debug
+spring.cloud.alibaba.fescar.tx-service-group=my_test_tx_group
\ No newline at end of file
diff --git a/springcloud-jpa-seata/user-service/src/main/resources/file.conf b/springcloud-jpa-seata/user-service/src/main/resources/file.conf
new file mode 100644
index 000000000..60e5d2557
--- /dev/null
+++ b/springcloud-jpa-seata/user-service/src/main/resources/file.conf
@@ -0,0 +1,41 @@
+transport {
+ # tcp udt unix-domain-socket
+ type = "TCP"
+ #NIO NATIVE
+ server = "NIO"
+ #enable heartbeat
+ heartbeat = true
+ #thread factory for netty
+ 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"
+ # netty boss thread size,will not be used for UDT
+ boss-thread-size = 1
+ #auto default pin or 8
+ worker-thread-size = 8
+ }
+}
+service {
+ #vgroup->rgroup
+ vgroup_mapping.my_test_tx_group = "default"
+ #only support single node
+ default.grouplist = "127.0.0.1:8091"
+ #degrade current not support
+ enableDegrade = false
+ #disable
+ disable = false
+ disableGlobalTransaction = false
+}
+
+client {
+ async.commit.buffer.limit = 10000
+ lock {
+ retry.internal = 10
+ retry.times = 30
+ }
+}
diff --git a/springcloud-jpa-seata/user-service/src/main/resources/registry.conf b/springcloud-jpa-seata/user-service/src/main/resources/registry.conf
new file mode 100644
index 000000000..3b926a282
--- /dev/null
+++ b/springcloud-jpa-seata/user-service/src/main/resources/registry.conf
@@ -0,0 +1,51 @@
+registry {
+ # file 、nacos 、eureka、redis、zk
+ type = "file"
+
+ nacos {
+ serverAddr = "localhost"
+ namespace = "public"
+ cluster = "default"
+ }
+ eureka {
+ serviceUrl = "http://localhost:1001/eureka"
+ application = "default"
+ weight = "1"
+ }
+ redis {
+ serverAddr = "localhost:6381"
+ db = "0"
+ }
+ zk {
+ cluster = "default"
+ serverAddr = "127.0.0.1:2181"
+ session.timeout = 6000
+ connect.timeout = 2000
+ }
+ file {
+ name = "file.conf"
+ }
+}
+
+config {
+ # file、nacos 、apollo、zk
+ type = "file"
+
+ nacos {
+ serverAddr = "localhost"
+ namespace = "public"
+ cluster = "default"
+ }
+ apollo {
+ app.id = "fescar-server"
+ apollo.meta = "http://192.168.1.204:8801"
+ }
+ zk {
+ serverAddr = "127.0.0.1:2181"
+ session.timeout = 6000
+ connect.timeout = 2000
+ }
+ file {
+ name = "file.conf"
+ }
+}
\ No newline at end of file