• 在Spring Boot中使用数据库事务


    我们在前面已经分别介绍了如何在Spring Boot中使用JPA(初识在Spring Boot中使用JPA)以及如何在Spring Boot中输出REST资源( 在Spring Boot中输出REST资源)。那么关于数据库访问还有一个核心操作那就是事务的处理了,前面两篇博客小伙伴们已经见识到Spring Boot带给我们的巨大便利了,其实不用猜,我们也知道Spring Boot在数据库事务处理问题上也给我们带来惊喜,OK,废话不多说,就来看看如何在Spring Boot中使用事务吧。
    可能还是会有一些小伙伴对Spring Boot并不是特别熟悉,不熟悉的小伙伴请移步这里从SpringMVC到Spring Boot,老司机请忽略。

    OK,那我们开始今天愉快的coding旅程吧!

    创建Project并添加数据库依赖

    这个没啥好说的,不懂如何创建一个Spring Boot工程的小伙伴请移步这里初识Spring Boot框架。创建的时候选择依赖时选择Web和JPA,如下图:
    这里写图片描述
    OK,工程创建成功之后接下来我们来添加数据库驱动,和前文一样,我这里还是以MySql数据库为例,在pom.xml文件中添加如下依赖:

    <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.40</version>
            </dependency>

    配置application.properties

    配置方式还是和前文一模一样,不懂的小伙伴请移步这里初识在Spring Boot中使用JPA,我这里直接贴代码,含义不再赘述:

    spring.datasource.driver-class-name=com.mysql.jdbc.Driver
    spring.datasource.url=jdbc:mysql://localhost:3306/rest
    spring.datasource.username=root
    spring.datasource.password=sang
    
    spring.jpa.hibernate.ddl-auto=update
    spring.jpa.show-sql=true
    spring.jackson.serialization.indent_output=true

    创建实体类

    实体类还是一个Person,如下:

    @Entity
    public class Person {
        @Id
        @GeneratedValue
        private Long id;
        private String name;
        private String address;
        private Integer age;
    
        public Person() {
        }
    
        public Long getId() {
            return id;
        }
    
        public void setId(Long id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
        public Person(Long id, String name, String address, Integer age) {
            this.id = id;
            this.name = name;
            this.address = address;
            this.age = age;
        }
    }

    创建实体类的Repository

    public interface PersonRepository extends JpaRepository<Person,Long> {
    }

    这里因为我们的目的是测试事务,所以Repository中暂时先不写任何东西。

    创建业务服务Service

    创建Service接口

    public interface DemoService {
        public Person savePersonWithRollBack(Person person);
    
        public Person savePersonWithoutRollBack(Person person);
    }

    创建Service实现类

    @Service
    public class DemoServiceImpl implements DemoService {
        @Autowired
        PersonRepository personRepository;
    
        @Transactional(rollbackFor = {IllegalArgumentException.class})
        @Override
        public Person savePersonWithRollBack(Person person) {
            Person p = personRepository.save(person);
            if (person.getName().equals("sang")) {
                throw new IllegalArgumentException("sang 已存在,数据将回滚");
            }
            return p;
        }
    
        @Transactional(noRollbackFor = {IllegalArgumentException.class})
        @Override
        public Person savePersonWithoutRollBack(Person person) {
            Person p = personRepository.save(person);
            if (person.getName().equals("sang")) {
                throw new IllegalArgumentException("sang已存在,但数据不会回滚");
            }
            return p;
        }
    }

    在这里我们使用到了@Transactional注解,该注解中有一个rollbackFor属性,该属性的值为数组,表示当该方法中抛出指定的异常时数据回滚,该注解还有个属性叫noRollbackFor,表示当该方法中抛出指定的异常时数据不回滚,这两个属性我们分别在两个方法中体现。

    创建控制器

    @RestController
    public class MyController {
        @Autowired
        private DemoService demoService;
    
        @RequestMapping("/norollback")
        public Person noRollback(Person person) {
            return demoService.savePersonWithoutRollBack(person);
        }
    
        @RequestMapping("/rollback")
        public Person rollback(Person person) {
            return demoService.savePersonWithRollBack(person);
        }
    }

    控制器创建成功之后接下来我们就可以直接在浏览器中访问这两个地址看看效果了。

    测试

    首先在浏览器中输入http://localhost:8080/rollback?name=sang&age=100,我们来测试回滚的情况,访问结果如下:
    这里写图片描述
    看看控制台抛出的异常:
    这里写图片描述
    这个时候再去查看数据库,发现数据表中并没有插入数据。

    再在地址栏输入http://localhost:8080/norollback?name=sang&age=100,测试结果如下:
    浏览器依然报错:
    这里写图片描述
    控制台也打印了错误,但是这个时候再去看数据库,数据已成功插入了。如下图:
    这里写图片描述

    OK,以上就是数据库事务在Spring Boot中的简单使用。

    本文案例下载:
    本文案例GitHub地址https://github.com/lenve/JavaEETest/tree/master/Test24-Transaction

    更多Spring Boot资料请移步这里从SpringMVC到Spring Boot

    以上。

    参考资料:
    《JavaEE开发的颠覆者 Spring Boot实战》第八章

  • 相关阅读:
    方法是Objective-C独有的一种结构,只能在Objective-C中声明、定义和使用,C语言不能声明、定义和使用
    NSDate
    runtime
    iOS开发常用的工具
    程序的国际化
    经常使用的iOS SDK库和第三方库
    RunLoop是什么?
    狼若回头,必有理由
    第1年1月21日 Guard Malloc
    第1年1月10日 flv格式
  • 原文地址:https://www.cnblogs.com/qitian1/p/6461634.html
Copyright © 2020-2023  润新知