欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring5(23) —— 回顾事务

程序员文章站 2022-07-12 10:07:44
...


1.回顾事务

  • 事务特性:要么都成功,要么都失败
  • 事务在项目开发中十分重要,涉及到数据一致性问题,不能马虎
  • 它用于确保数据一致性

事务的ACID原则

  1. 原子性:事务不可分割
  2. 一致性:事务执行不管成不成功,所有人的数据要一致;比如转账,那么参与转账双方的钱的总和应该保持不变
  3. 隔离性:操作同一数据的不同事务之间相互独立,互不干扰
  4. 持久性:事务成功之后,其结果必须影响数据库中的数据;即使事务失败,也要求使用某种机制恢复数据

2.代码实现

1.项目搭建

    首先我们再来回顾一下spring整合mybatis

  • 创建新项目:Spring-11-Transaction

  • 子model依赖添加

    <?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">
       <parent>
           <artifactId>Spring-Study</artifactId>
           <groupId>com.thhh</groupId>
           <version>1.0-SNAPSHOT</version>
       </parent>
       <modelVersion>4.0.0</modelVersion>
    
       <artifactId>Spring-11-Transaction</artifactId>
       <dependencies>
           <!--junit依赖-->
           <dependency>
               <groupId>junit</groupId>
               <artifactId>junit</artifactId>
               <version>4.12</version>
           </dependency>
           <!--数据库依赖-->
           <dependency>
               <groupId>mysql</groupId>
               <artifactId>mysql-connector-java</artifactId>
               <version>5.1.47</version>
           </dependency>
           <!--mybatis依赖-->
           <dependency>
               <groupId>org.mybatis</groupId>
               <artifactId>mybatis</artifactId>
               <version>3.5.2</version>
           </dependency>
           <!--spring依赖-->
           <dependency>
               <groupId>org.springframework</groupId>
               <artifactId>spring-webmvc</artifactId>
               <version>5.2.8.RELEASE</version>
           </dependency>
           <!--spring操作数据库,需要再导入一个spring-jdbc这个依赖-->
           <dependency>
               <groupId>org.springframework</groupId>
               <artifactId>spring-jdbc</artifactId>
               <version>5.2.8.RELEASE</version>
           </dependency>
           <!--AOP织入包,简单理解,支持切入点表达式等等-->
           <dependency>
               <groupId>org.aspectj</groupId>
               <artifactId>aspectjweaver</artifactId>
               <version>1.9.4</version>
           </dependency>
           <!--mybatis-spring整合依赖-->
           <dependency>
               <groupId>org.mybatis</groupId>
               <artifactId>mybatis-spring</artifactId>
               <version>2.0.5</version>
           </dependency>
           <!--lombok依赖-->
           <dependency>
               <groupId>org.projectlombok</groupId>
               <artifactId>lombok</artifactId>
               <version>1.18.12</version>
           </dependency>
       </dependencies>
    
    </project>
    
  • 创建实体类

    package com.thhh.pojo;
    
    import lombok.Data;
    
    @Data
    public class User {
        private int id;
        private String name;
        private String pwd;
    }
    
  • 有了实体类就为它创建一个mapper接口

    package com.thhh.mapper;
    
    import com.thhh.pojo.User;
    
    import java.util.List;
    
    public interface UserMapper {
        public List<User> queryUserList();
    }
    
  • 有了mapper接口就为它创建一个mapper.xml

    <?xml version="1.0" encoding="UTF8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <mapper namespace="com.thhh.mapper.UserMapper">
        <select id="queryUserList" resultType="user">
            select * from mybatis.user
        </select>
    </mapper>
    
  • 有了mapper.xml就去mybatis核心配置文件中注册,注意这一点,原来单独使用mybatis的时候,配置文件中的内容比较多,现在我们将spring和mybatis进行了整合,mybatis中一般只剩下了typealiases和setting节点的配置,其他配置都迁移到spring容器中

    <?xml version="1.0" encoding="UTF8" ?>
    <!DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
        <!--类型别名节点-->
        <typeAliases>
            <package name="com.thhh.pojo"/><!--直接包扫描,我们可以使用类名,首字母大小写都可以-->
        </typeAliases>
    
    </configuration>
    
  • 整合mybatis,创建spring配置文件,这里我们为了规范,先创建一个整个mybatis的配置文件spring-dao.xml,再创建一个总的配置文件applicationContext.xml;spring-dao.xml负责整合mybatis(即只装配两个bean,dataSource和sqlSessionFactory),applicationContext.xml用于引入spring-dao.xml和装配bean(其他的bean都装配到这个spring容器中)

    • spring-dao.xml
    <?xml version="1.0" encoding="UTF8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            https://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/aop
            https://www.springframework.org/schema/aop/spring-aop.xsd">
    
        <!--数据源datasources:是呀spring的数据源替换mybatis的配置-->
        <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
            <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useUnicode=true&amp;characterEncoding=UTF-8&amp;useSSL=false"/>
            <property name="username" value="root"/>
            <property name="password" value="123"/>
        </bean>
        <!--sqlsessionFactory-->
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="dataSource" />
            <!--绑定mybatis配置文件-->
            <property name="configLocation" value="classpath:mybatis-config.xml"/><!--这样两个配置文件就联动起来了-->
            <property name="mapperLocations" value="classpath:com/thhh/mapper/*.xml"/><!--配置注册mapper.xml,对应mybatis中的注册mapper节点-->
        </bean>
    </beans>
    
    • applicationContext.xml
    <?xml version="1.0" encoding="UTF8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns:aop="http://www.springframework.org/schema/aop"
          xsi:schemaLocation="http://www.springframework.org/schema/beans
           https://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/aop
           https://www.springframework.org/schema/aop/spring-aop.xsd">
       <!--导入整合mybatis的子容器,最后所有的容器会整合成一个大容器-->
       <import resource="spring-dao.xml"/>
    
       <!--装配bean-->
       <!--方式2配置sqlsession-->
       <bean id="userMapperImpl" class="com.thhh.mapper.UserMapperImpl">
           <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
       </bean>
    
    </beans>
    
  • 整合spring和mybatis的时候我们需要新增一个mapper接口的实现类来封装mybatis的操作,即UserMapperImpl

    package com.thhh.mapper;
    
    import com.thhh.pojo.User;
    import org.mybatis.spring.support.SqlSessionDaoSupport;
    
    import java.util.List;
    
    public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper{
    
       @Override
       public List<User> queryUserList() {
           return getSqlSession().getMapper(UserMapper.class).queryUserList();
       }
    }
    
  • 测试

    import com.thhh.mapper.UserMapper;
    import com.thhh.pojo.User;
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import java.util.List;
    
    public class MyTest {
        @Test
        public void test01(){
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
            UserMapper userMapper = context.getBean("userMapperImpl", UserMapper.class);
            List<User> userList = userMapper.queryUserList();
            for (User user : userList) {
                System.out.println(user);
            }
        }
    }
    

Spring5(23) —— 回顾事务

2.代码实现

需求:制造错误,用于认识spring操作中不使用事务的危险性

  • 添加一个新增和删除用户操作
    package com.thhh.mapper;
    
    import com.thhh.pojo.User;
    import org.apache.ibatis.annotations.Param;
    
    import java.util.List;
    
    public interface UserMapper {
        //1、查询所有用户
        public List<User> queryUserList();
    
        //2、新增用户
        public int addUser(User user);//非基本数据类型不要写@Param注解,否则会报错
        
        //3、删除用户
        public int deleteUser(@Param("id") int id);
    }
    
  • 修改实现类
    package com.thhh.mapper;
    
    import com.thhh.pojo.User;
    import org.mybatis.spring.support.SqlSessionDaoSupport;
    
    import java.util.List;
    
    public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper{
    
        @Override
        public List<User> queryUserList() {
            return getSqlSession().getMapper(UserMapper.class).queryUserList();
        }
    
        @Override
        public int addUser(User user) {
            return getSqlSession().getMapper(UserMapper.class).addUser(user);
        }
    
        @Override
        public int deleteUser(int id) {
            return getSqlSession().getMapper(UserMapper.class).deleteUser(id);
        }
    }
    
  • 去mapper.xml中编写SQL
    <?xml version="1.0" encoding="UTF8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <mapper namespace="com.thhh.mapper.UserMapper">
        <!--1、查询用户-->
        <select id="queryUserList" resultType="user">
            select * from mybatis.user
        </select>
        <!--2、新增用户-->
        <insert id="addUser" parameterType="user">
            insert into mybatis.user (id, name, pwd) values (#{id},#{name},#{pwd});
        </insert>
        <!--3、删除用户-->
        <delete id="deleteUser">
            delete from mybatis.user where id=#{id}
        </delete>
    </mapper>
    
  • 制造一个错误,把delete关键字后面添加一个"S",那么delete操作显然使用报错的
    Spring5(23) —— 回顾事务
    Spring5(23) —— 回顾事务
  • 修改查询实现的mybatis对应的代码
        @Override
        public List<User> queryUserList() {
            User user = new User(10,"10号","123");
            UserMapper userMapper = getSqlSession().getMapper(UserMapper.class);
            userMapper.addUser(user);
            deleteUser(10);
            return userMapper.queryUserList();
        }
    

Spring5(23) —— 回顾事务
Spring5(23) —— 回顾事务
Spring5(23) —— 回顾事务
Spring5(23) —— 回顾事务