1、什么是事物

(1)事务是数据库操作最基本单元,逻辑上一组操作,要么都成功,如果有一个失败所有操作都失败
(2)典型场景:银行转账

2、事务四个特性(ACID)

(1)原子性(要么都成功,要么都失败)
(2)一致性(操作之前和操作之后,总量不变。)
(3)隔离性(在多事务操作的时候,相互之间不会产生影响)
(4)持久性(操作完之后数据真正存储在表中,永久保存)

3、事务操作(搭建事务操作环境)

(1)创建数据库表并添加记录
image.png
(2)创建Dao类和实现类

  1. package com.daijunyi.dao;
  2. public interface AccountDao {
  3. public void changeMoneyById(Integer userId,Double money);
  4. }
  1. package com.daijunyi.dao;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.jdbc.core.JdbcTemplate;
  4. import org.springframework.stereotype.Repository;
  5. @Repository
  6. public class AccountDaoImp implements AccountDao {
  7. @Autowired
  8. private JdbcTemplate jdbcTemplate;
  9. @Override
  10. public void changeMoneyById(Integer userId, Double money) {
  11. String sql = "update t_account set money=money+? where id=?";
  12. Object[] args = {money,userId};
  13. int update = jdbcTemplate.update(sql, args);
  14. System.out.println("操作结果:"+update);
  15. }
  16. }

(3)创建service类

  1. package com.daijunyi.service;
  2. import com.daijunyi.dao.AccountDao;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.stereotype.Service;
  5. @Service
  6. public class AccountService {
  7. @Autowired
  8. private AccountDao accountDao;
  9. public void changeMoney(Integer fromUserId,Integer toUserId,Double changeMoney){
  10. accountDao.changeMoneyById(fromUserId,-changeMoney);
  11. accountDao.changeMoneyById(toUserId,changeMoney);
  12. }
  13. }

(4)配置数据库properties文件

  1. druid.driver=com.mysql.cj.jdbc.Driver
  2. druid.url=jdbc:mysql://localhost:3306/learn
  3. druid.username=root
  4. druid.password=qwerasdf123

(5)创建bean.xml并且配置

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
  6. http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
  7. <!--开启主键扫描-->
  8. <context:component-scan base-package="com.daijunyi"/>
  9. <!--引入外部属性文件-->
  10. <context:property-placeholder location="classpath:db.properties"/>
  11. <!--配置datasource 数据库连接池-->
  12. <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
  13. <property name="driverClassName" value="${druid.driver}"/>
  14. <property name="url" value="${druid.url}"/>
  15. <property name="username" value="${druid.username}"/>
  16. <property name="password" value="${druid.password}"/>
  17. </bean>
  18. <!--配置jdbcTemplate对象-->
  19. <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
  20. <property name="dataSource" ref="dataSource"/>
  21. </bean>
  22. </beans>

(6)测试

    @Test
    public void testChangeMoney(){

        ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");

        AccountService accountService = (AccountService) context.getBean("accountService");

        accountService.changeMoney(1,2,100.0);
    }

结果
image.png

这是正常请求,如果中间发生了错误,比如我们在service类中

@Service
public class AccountService {

    @Autowired
    private AccountDao accountDao;

    public void changeMoney(Integer fromUserId,Integer toUserId,Double changeMoney){
        accountDao.changeMoneyById(fromUserId,-changeMoney);
        int i=1/0;
        accountDao.changeMoneyById(toUserId,changeMoney);
    }
}

这样做 我们在恢复到每个人都1000块钱的时候,再次执行就会产生错误
结果为:
image.png
就少了100了,接下去我们就来用事物解决这个问题