zoukankan      html  css  js  c++  java
  • 第10章—开启事务

    spring boot 系列学习记录:http://www.cnblogs.com/jinxiaohang/p/8111057.html

    码云源码地址:https://gitee.com/jinxiaohang/springboot

      此前,我们主要通过XML配置Spring来托管事务。在SpringBoot则非常简单,只需在业务层添加事务注解(@Transactional )即可快速开启事务。虽然事务很简单,但对于数据方面是需要谨慎对待的,识别常见坑点对我们开发有帮助。

      推荐做法:在业务层统一抛出异常,然后在控制层统一处理。

    1. 引入依赖

    如果是新建项目的,可以在这页添加依赖,如是原有项目可直接编写。

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>com.xiaohang</groupId>
        <artifactId>springboot-transactional</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <packaging>jar</packaging>
    
        <name>springboot-transactional</name>
        <description>Demo project for Spring Boot</description>
    
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>1.5.9.RELEASE</version>
            <relativePath/> <!-- lookup parent from repository -->
        </parent>
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
            <java.version>1.8</java.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-jpa</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <scope>runtime</scope>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    
    </project>

    二、添加数据源

    spring:
      datasource:
        url: jdbc:mysql://localhost:3306/test?useSSL=false
        username: root
        password: root
        driver-class-name: com.mysql.jdbc.Driver
    
      jpa:
        hibernate:
          ddl-auto: update
        show-sql: true

    三、编写各层代码

    • 实体层
    import lombok.Data;
    
    import javax.persistence.Entity;
    import javax.persistence.Id;
    import java.math.BigDecimal;
    
    @Data
    @Entity
    public class UserAccount {
    
        @Id
        private String userId;
    
        private String userName;
    
        private BigDecimal balance;
    }
    • dao层
    import com.xiaohang.springboottransactional.entity.UserAccount;
    import org.springframework.data.jpa.repository.JpaRepository;
    
    public interface UserAccountRepository extends JpaRepository<UserAccount,String>{
    }
    • service层
    public interface UserAccountService {
        /**
         * 转账
         */
        public UserAccount change(String userId,BigDecimal bigDecimal,String userId2) throws Exception;
    }
    • service实现层
    import com.xiaohang.springboottransactional.entity.UserAccount;
    import com.xiaohang.springboottransactional.repository.UserAccountRepository;
    import com.xiaohang.springboottransactional.service.UserAccountService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Transactional;
    
    import java.math.BigDecimal;
    
    @Service
    public class UserAccountServiceImpl implements UserAccountService {
    
        @Autowired
        private UserAccountRepository userAccountRepository;
    
        @Transactional
        @Override
        public UserAccount change(String userId, BigDecimal bigDecimal, String userId2) throws Exception{
            UserAccount userAccount = userAccountRepository.findOne(userId);
            UserAccount userAccount2 = userAccountRepository.findOne(userId2);
            userAccount.setBalance(userAccount.getBalance().add(bigDecimal));
            userAccount2.setBalance(userAccount2.getBalance().subtract(bigDecimal));
            userAccountRepository.save(userAccount);
            int n=1/0;//throw new Exception();//假设发生故障
            userAccountRepository.save(userAccount2);
            return userAccountRepository.findOne(userId);
    
        }
    }
    • 测试层
    import com.xiaohang.springboottransactional.service.UserAccountService;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringRunner;
    import java.math.BigDecimal;
    
    
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class UserAccountServiceImplTest {
    
        @Autowired
        private UserAccountService userAccountService;
    
        @Test
        public void change() throws Exception {
            try {
                System.out.println(userAccountService.change("1",new BigDecimal("100"),"2"));
            }catch (Exception e){
                System.out.println("抛出异常");
            }
        }
    
    }

    三、测试


     原始数据:


     不开启事务,不抛出异常时:


     不开启事务,抛出异常时(转账时发生错误,钱扣完,但是对方钱未到账;或者钱到帐了,但是钱未扣。)


     先恢复数据:

     开启事务,抛出异常时。

  • 相关阅读:
    浏览器工作原理
    Linux内存性能指标、CPU性能指标
    性能结果分析
    javascript事件与event对象的属性
    JavaScript的内置对象和浏览器对象
    互联网协议
    DNS原理
    浏览器缓存知识归纳
    LR性能指标分析
    使用dynatrace+showslow进行前端性能测试
  • 原文地址:https://www.cnblogs.com/jinxiaohang/p/8296549.html
Copyright © 2011-2022 走看看