SpringBoot学习笔记九:springBoot整合Mybatis3.x实现增删改查以及事务操作

1. SpringBoot学习笔记九:springBoot整合Mybatis3.x实现增删改查

文章目录

      • 1. SpringBoot学习笔记九:springBoot整合Mybatis3.x实现增删改查
        • 1.1. 配置文件
        • 1.2. Mapper映射
        • 1.3. 事务和隔离级别
        • 1.4. 个人对事务的理解
          • 1.4.1. 事务的特性
          • 1.4.2. 当并发操作事务时,可能会产生四个情况
          • 1.4.3. 解决四种情况:隔离级别的出现
        • 1.5. 测试事务

1.1. 配置文件

  1. 让控制台打印出sql语句
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

1.2. Mapper映射

  1. 查询
    • column对应的是数据库中的字段,property对应的是对象中的字段
@Select("select * from t_user")
@Results({
    @Result(column="create_time",property="createTime"),
    @Result(column="create_time",property="createTime")

})
List<User2> getAll();
  1. 条件查询
@Select("select * from t_user where id=#{id}")
@Results({
    @Result(column = "create_time",property = "createTime")
})
User2 findById(Long id);
  1. 更新
@Update("update t_user set name=#{name} where id=#{id}")
void update(User2 user2);
  1. 删除
@Delete("Delete From t_user where id=#{userId}")
void delete(Long userId);
  1. 接口
@GetMapping("/findAll")
public Object findAll() {
    return JsonData.buildSuccess(userMapper.getAll());
}

@GetMapping("find_by_id")
public Object findById(long id) {
    return JsonData.buildSuccess(userMapper.findById(id));
}
@GetMapping("/del_by_id")
public Object delById(long id) {
    userMapper.delete(id);
    return JsonData.buildSuccess();
}
@GetMapping("/update")
public Object update(String name,int id) {
    User2 user2=new User2();
    user2.setName(name);
    user2.setId(id);
    userMapper.update(user2);
    return JsonData.buildSuccess();
}

1.3. 事务和隔离级别

  1. 事务种类:分为,单机事务和分布式事务处理。
  2. 隔离级别

Serializable:最严格,串行处理,消耗资源大。不会出现脏读,幻读等情况,但是性能也随之下降。

Repeatable Read​ :保证了一个事务不会修改已经由另一个事务读取但未提交的数据。(不可重复读)

Read Committed:大多数主流数据库的默认事务等级。

Read Uncommitted:保证了读取过程中不会读取到非法数据。

  1. 事务的传播行为:

PROPAGATION_REQUIRED—支持当前事务,如果当前没有事务,就新建一个事务,最常见的选择。

PROPAGATION_SUPPORTS—支持当前事务,如果当前没有事务,就以非事务方式执行。

PROPAGATION_MANDATORY—支持当前事务,如果当前没有事务,就抛出异常。

PROPAGATION_REQUIRES_NEW—新建事务,如果当前存在事务,把当前事务挂起,两个事务之间没有关系,一个异常,一个提交,不会同时回滚。

PROPAGATION_NOT_SUPPORTED—以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

PROPAGATION_NEVER–以非事务方式执行,如果当前存在事务,则抛出异常。

  1. 单机事务和分布式事务

SpringBoot学习笔记九:springBoot整合Mybatis3.x实现增删改查以及事务操作_第1张图片

  1. 分布式事务,出现问题解决方案:消息队列或者最终一致性方案

SpringBoot学习笔记九:springBoot整合Mybatis3.x实现增删改查以及事务操作_第2张图片

1.4. 个人对事务的理解

1.4.1. 事务的特性
  1. 原子性:多个数据库语句组成一个事务,要么多个数据库语句全部执行,要么都不执行,即:一旦有一个执行不成功,就全部回滚回去。
  2. 一致性:执行事务前后,保证数据一致,多个事务对同一个数据读取的结果是相同的。假如在并发转账过程中,参与者有A、B、C、D四个账户,如果参与者账户的总钱数是1000元,那么在并发事务转账后,最后四个账户总钱数还是1000元。这就是前后结果一致性。
  3. 隔离性:并发事务中,事务之间是隔离的,这个事务的操作和另一个事务是没有关系的。
  4. 持久性:一旦事务提交,对数据库的改变是一定的,即使数据库发生故障,也不会有影响。要么数据库值改变,要么不改变。
1.4.2. 当并发操作事务时,可能会产生四个情况
  1. 脏读:由于事务是隔离性质的,当一个事务要修改数据时,另一个事务也在操作,并在第一个事务操作之前取走了数据,比如:花呗已经查询到你支付宝里有500元,就打算将这500元改为0(要扣掉你仅剩的500元),此时你眼疾手快,拿走了这500元支付了一件衣服,支付衣服率先取走了500元,此时花呗正准备将500修改为0,马云爸爸就凭空丢失了500元。(查询和更新数据是两个操作)在查询后,你就先取走了500元。
  2. 不可重复读:事务A执行两次查询操作,事务b执行一次修改操作。假如事务A第一次查询你余额宝里有500元,正准备执行第二次查询,此时你又将500元买衣服了(事务B),那么事务A第二次查询结果就和第一次不一样了。
  3. 幻读:事务A继续执行两次查询你的账单操作,第一次查询你有一个账单,此时你有买了一件衣服,又生成一个账单,当事务A第二次查询时发现账单数目和第一次不同。(幻读和不可重复读的区别是:不可重复读是修改,幻读是新增)
  4. 丢失修改:事务A和事务B同时进来了,事务A是要扣掉你500元,事务b是添加500块钱,那么事务A的修改就丢失了。
  5. 事务产生这些问题的原因是事务是两步操作:先操作数据库,然后提交,只有提交了才会持久化写入数据库,如果没有提交,表示该事务还未结束,但是数据库的值已经修改了,不过还是可以回滚的。
1.4.3. 解决四种情况:隔离级别的出现
  1. 读取未提交:read Uncommited:事务可以读取未提交的数据,这个肯定不行,会出现很多问题。
  2. 读取已经提交的:read commited:这样就不会出现脏读了,但是幻读和不可重复读还是会出现的,比如:你查询到你账户有5000元,此时另一个你的亲人操作该账户,取走5000元并提交了事务,如果你拿着卡去消费时,会发现消费失败,你就纳闷了。明明有钱为什么无法消费?这就是不可重复读和幻读。
  3. 可重复读:REPEATABLE- READ:阻止了脏读和不可重复读,但是幻读仍有可能发生。
  4. 可串行化SERIALIZABLE:完全服从ACID的隔离机制(原子性,一致性,隔离性,持久性)。
  5. mysql的InnodB存储引擎,可以避免幻读,达到了可串行化隔离级别,但性能没有下降。采用了Next key-Lock算法。

1.5. 测试事务

  1. 在未添加事务时,如果数据库操作中出现异常,数据库中仍然会插入记录
@Override
public int addAccount() {
    // TODO Auto-generated method stub
    User2 user2=new User2();
    user2.setAge(88);
    user2.setCreateTime(new Date());
    user2.setName("测试事务,加入事务");
    user2.setPhone("125645884");
    userMapper.insert(user2);
    int q=3/0;
    return 0;
}

未插入事务之前

  1. 在数据库中添加事务
    • 添加事务后,当出现异常时,就会回滚,不会插入记录。
@Override
@Transactional(propagation = Propagation.REQUIRED)//指定隔离级别或者默认
public int addAccount() {
    // TODO Auto-generated method stub
    User2 user2=new User2();
    user2.setAge(88);
    user2.setCreateTime(new Date());
    user2.setName("测试事务,加入事务");
    user2.setPhone("125645884");
    userMapper.insert(user2);
    int q=3/0;
    return 0;
}

插入事务之后

你可能感兴趣的:(springBoot笔记)