Spring Boot(五)事务管理

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/li13168690086/article/details/82497403

写在前面:本次讲解均在MAC OS环境下进行;因为对于数据库,我们在增删改的过程中可能会发生错误,导致存储数据不一致,而事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。

目录

  • Innodb与Myisam引擎的区别于应用场景

  • 实例操作

一、Innodb与Myisam引擎的区别于应用场景

  Innodb和Myisam是mysql的两种引擎,我在初次尝试事务管理时,遇到了引擎这个问题,当时我的mysql默认是用了Myisam,结果没有达到我想要的效果,下面就说说这两种引擎有什么不同。参考博文fengna

  1、Innodb

  •    事物安全型引擎,支持事务处理等高级处理。
  •    行级锁(可以参考这篇锁机制
  • 对于INSERT和UPDATE操作有很好的适应性,面对大量的这两类操作,Innodb更好的选择。
  • 查询方式:因为其不保存表的具体行数,所以在执行select count(*) from table时,要扫描一边整个表来计算有少行。
  • 支持外键
  • 在做select操作时,维护的东西相对Myisam要多:要缓存数据库、寻址要映射到块再到行、维护MVCC一致(即使你的场景没有,它也要去维护)

总结:适合(1)做可靠性要求比较高,或者进行事物处理;(2)对表更新和插入相当频繁,并且行锁定的机会比较大的情况

  2、Myisam

  • 非事物安全型
  • 表锁级(可以参考这篇锁机制
  • 对于大量的select,它支持的比较好
  • Myisam保存行数,所以对于select count(*) from table操作,它只需简单读出保存好的行数。
  • 不支持外键
  • 查询速度快:只需缓存索引块、寻址直接记录文件的offset、不需要维护MVCC一致

总结:适合(1)做很多count计算(2)插入不频繁,但查询非常频繁(3)没有事物处理

此外提醒一点在进行select count(*) from table操作时,如果count(*)语句包含   where条件时,两种引擎的操作是一样的。

在了解以上区别后,对于我们现在要进行的事务管理,我们应该选择Innodb引擎,但我开头说了,我建的表默认是Myisam,所以下面讲解下如何更改引擎。

3、更改mysql引擎

  我是直接用代码来修改的,因为我表的数据很少,所以可以直接这样,但如果数据量多请参考这篇文章

  我用的是sequel pro管理数据库,所以就直接在里面改了,下面是截图  

P1
图1

在query窗口输入:ALTER TABLE girl ENGINE=InnoDb ,其中girl是表名,然后点击Run Current按钮运行即可。

二、实例操作

  实例描述:给girl表同时插入两条女生记录,测试时特地使其中一个女生的记录有错无法插入,观察另一条女生记录是否被存储(期望是要么都被成功存入,要么都不被存入

  1、在spring boot里新建事物类

package com.imooc.girl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;

@Service
public class GirlService {

    @Autowired
    private GirlRepository girlRepository;

    @Transactional
    public void insertTwo(){
        Girl girlA = new Girl();
        girlA.setCupSize("A");
        girlA.setAge(18);
        girlRepository.save(girlA);

        Girl girlB = new Girl();
        girlB.setCupSize("B");
        girlB.setAge(19);
        girlRepository.save(girlB);
    }
}

截图:

P2
图2

2、在GirlController类里添加插入方法  

package com.imooc.girl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Optional;

@RestController
public class GirlController {

    @Autowired
    private GirlService girlService;
    
    /**
     * 事物处理测试
     */
    @PostMapping(value = "/girls/two")
    public void girlTwo(){
        girlService.insertTwo();
    }

}

测试是否都能成功添加:

P3
图3

没问题,接下来开始进入场景:将cupSize的值在数据库中限制长度为1,然后在插第二条记录时故意将cupSize赋值长度超过1,看能否达到期望。

  修改属性:

P4
图4

重新赋值:

P5
图5

清空数据库,重新测试:

p6
图6

如上图所示,成功报错,接下来看下数据库情况: 

P7
图7

很好,没有存储任何一条记录!

  我们回到刚才建立的事务类(见下面代码),其中起关键作用的是@Transactional这个注解,这个注解就是在spring里用于事物管理功能的(你可以试着将此注解删除,看还能不能进行事物管理,这里就不演示了

package com.imooc.girl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;

@Service
public class GirlService {

    @Autowired
    private GirlRepository girlRepository;

    @Transactional
    public void insertTwo(){
        Girl girlA = new Girl();
        girlA.setCupSize("A");
        girlA.setAge(18);
        girlRepository.save(girlA);

        Girl girlB = new Girl();
        girlB.setCupSize("B");
        girlB.setAge(19);
        girlRepository.save(girlB);
    }
}
展开阅读全文

没有更多推荐了,返回首页