Spring整合MyBatis、声明式事务

Spring整合MyBatis

步骤:

  1. 导入相关jar包

    • junit
    • mybatis
    • mysql
    • spring相关
    • aop织入
    • mybatis-spring

    pom.xml配置文件:

    
    <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">
        <modelVersion>4.0.0modelVersion>
        <parent>
            <groupId>org.examplegroupId>
            <artifactId>Spring-StudyartifactId>
            <version>1.0-SNAPSHOTversion>
        parent>
    
        <artifactId>spring-10-mybatisartifactId>
    
        <dependencies>
            <dependency>
                <groupId>org.junit.jupitergroupId>
                <artifactId>junit-jupiter-apiartifactId>
                <version>5.10.0version>
                <scope>testscope>
            dependency>
    
            <dependency>
                <groupId>mysqlgroupId>
                <artifactId>mysql-connector-javaartifactId>
                <version>8.0.28version>
            dependency>
    
            <dependency>
                <groupId>org.mybatisgroupId>
                <artifactId>mybatisartifactId>
                <version>3.5.13version>
            dependency>
    
            <dependency>
                <groupId>org.springframeworkgroupId>
                <artifactId>spring-webmvcartifactId>
                <version>6.0.11version>
            dependency>
    
            
            <dependency>
                <groupId>org.springframeworkgroupId>
                <artifactId>spring-jdbcartifactId>
                <version>5.3.12version>
            dependency>
    
            
            <dependency>
                <groupId>org.aspectjgroupId>
                <artifactId>aspectjweaverartifactId>
                <version>1.9.6version>
            dependency>
    
            
            <dependency>
                <groupId>org.mybatisgroupId>
                <artifactId>mybatis-springartifactId>
                <version>2.0.6version>
            dependency>
            
            <dependency>
                <groupId>org.projectlombokgroupId>
                <artifactId>lombokartifactId>
                <version>1.18.28version>
            dependency>
        dependencies>
    
        <properties>
            <maven.compiler.source>17maven.compiler.source>
            <maven.compiler.target>17maven.compiler.target>
            <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
        properties>
    
    project>
    
  2. 编写配置文件

  3. 测试

回顾MyBatis

数据库还用我们之前使用过的mybatis库

  1. 编写实体类

    实体类照着表写就好了

    package xyz.luck1y.pojo;
    
    import lombok.Data;
    
    @Data
    public class User {
        private int id;
        private String name;
        private String pwd;
    }
    

    这里偷懒用了Lombok,要导入包

  2. 编写核心配置文件

    
    <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">
        <modelVersion>4.0.0modelVersion>
        <parent>
            <groupId>org.examplegroupId>
            <artifactId>Spring-StudyartifactId>
            <version>1.0-SNAPSHOTversion>
        parent>
    
        <artifactId>spring-10-mybatisartifactId>
    
        <dependencies>
            <dependency>
                <groupId>org.junit.jupitergroupId>
                <artifactId>junit-jupiter-apiartifactId>
                <version>5.10.0version>
                <scope>testscope>
            dependency>
    
            <dependency>
                <groupId>mysqlgroupId>
                <artifactId>mysql-connector-javaartifactId>
                <version>8.0.28version>
            dependency>
    
            <dependency>
                <groupId>org.mybatisgroupId>
                <artifactId>mybatisartifactId>
                <version>3.5.13version>
            dependency>
    
            <dependency>
                <groupId>org.springframeworkgroupId>
                <artifactId>spring-webmvcartifactId>
                <version>6.0.11version>
            dependency>
    
            
            <dependency>
                <groupId>org.springframeworkgroupId>
                <artifactId>spring-jdbcartifactId>
                <version>5.3.12version>
            dependency>
    
            
            <dependency>
                <groupId>org.aspectjgroupId>
                <artifactId>aspectjweaverartifactId>
                <version>1.9.6version>
            dependency>
    
            
            <dependency>
                <groupId>org.mybatisgroupId>
                <artifactId>mybatis-springartifactId>
                <version>2.0.6version>
            dependency>
    
            <dependency>
                <groupId>org.projectlombokgroupId>
                <artifactId>lombokartifactId>
                <version>1.18.28version>
            dependency>
        dependencies>
    
        <properties>
            <maven.compiler.source>17maven.compiler.source>
            <maven.compiler.target>17maven.compiler.target>
            <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
        properties>
    
        <build>
            <resources>
                <resource>
                    <directory>src/main/resourcesdirectory>
                    <includes>
                        <include>**/*.propertiesinclude>
                        <include>**/*.xmlinclude>
                    includes>
                    <filtering>truefiltering>
                resource>
                <resource>
                    <directory>src/main/javadirectory>
                    <includes>
                        <include>**/*.propertiesinclude>
                        <include>**/*.xmlinclude>
                    includes>
                    <filtering>truefiltering>
                resource>
            resources>
        build>
    
    project>
    
  3. 编写mybatis-config配置文件

    
    DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
        <settings>
            
            <setting name="mapUnderscoreToCamelCase" value="true"/>
        settings>
    
        <typeAliases>
            <package name="xyz.luck1y.pojo"/>
        typeAliases>
    
        <environments default="development">
            <environment id="development">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                    <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT"/>
                    <property name="username" value="root"/>
                    <property name="password" value="123456"/>
                dataSource>
            environment>
        environments>
    
        <mappers>
            <mapper class="xyz.luck1y.mapper.UserMapper"/>
        mappers>
    configuration>
    
  4. 编写接口

    package xyz.luck1y.mapper;
    
    import xyz.luck1y.pojo.User;
    
    import java.util.List;
    
    public interface UserMapper {
        List<User> selectUser();
    }
    
  5. 编写Mapper.xml

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="xyz.luck1y.mapper.UserMapper">
        <select id="selectUser" resultType="user">
            select * from mybatis.user
        select>
    mapper>
    
  6. 测试

    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    import org.junit.jupiter.api.Test;
    import xyz.luck1y.mapper.UserMapper;
    import xyz.luck1y.pojo.User;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;
    
    public class MyTest {
        @Test
        public void test() throws IOException {
            String resources = "mybatis-config.xml";
            InputStream in = Resources.getResourceAsStream(resources);
            SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(in);
            SqlSession sqlSession = sessionFactory.openSession(true);
    
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            List<User> users = mapper.selectUser();
            for (User user : users) {
                System.out.println(user);
            }
            sqlSession.close();
        }
    }
    

MyBatis-Spring 整合方式一

MyBatis-Spring

官网:mybatis-spring –

MyBatis-Spring 会帮助你将 MyBatis 代码无缝地整合到 Spring 中。它将允许 MyBatis 参与到 Spring 的事务管理之中,创建映射器 mapper 和 SqlSession 并注入到 bean 中,以及将 Mybatis 的异常转换为 Spring 的 DataAccessException。 最终,可以做到应用代码不依赖于 MyBatis,Spring 或 MyBatis-Spring。

要使用 MyBatis-Spring 模块,只需要在类路径下包含 mybatis-spring-2.0.6.jar 文件和相关依赖即可。

要使用 MyBatis-Spring 模块,只需要在类路径下包含 mybatis-spring-3.0.2.jar 文件和相关依赖即可。

如果使用 Maven 作为构建工具,仅需要在 pom.xml 中加入以下代码即可:

<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatis-springartifactId>
<version>3.0.2version>
dependency>
  1. 编写数据源配置(此配置基本替代了原来mybatis-config配置文件)

    spring-dao.xml:

    
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
        
        
        <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
            <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT"/>
            <property name="username" value="root"/>
            <property name="password" value="123456"/>
        bean>
    
        
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="dataSource"/>
            
            <property name="configLocation" value="classpath:mybatis-config.xml"/>
            <property name="mapperLocations" value="classpath:xyz/luck1y/mapper/*.xml"/>
        bean>
    
        
        <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
            
            <constructor-arg index="0" ref="sqlSessionFactory"/>
        bean>
    
        
        <bean id="userMapper" class="xyz.luck1y.mapper.UserMapperImpl">
            <property name="sqlSession" ref="sqlSession"/>
        bean>
    
    beans>
    
  2. 给接口添加实现类(可选)

    package xyz.luck1y.mapper;
    
    import org.mybatis.spring.SqlSessionTemplate;
    import xyz.luck1y.pojo.User;
    
    import java.util.List;
    
    public class UserMapperImpl implements UserMapper {
    
        // 我们原来的所有操作都使用sqlSession来执行,现在都使用sqlSessionTemplate
        private SqlSessionTemplate sqlSession;
    
        public void setSqlSession(SqlSessionTemplate sqlSession) {
            this.sqlSession = sqlSession;
        }
    
        @Override
        public List<User> selectUser() {
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            return mapper.selectUser();
        }
    }
    
  3. 注入实现类到Spring容器中,新建一个Spring配置,专门用来处理除Mybatis配置外的配置(可选)

    applicationContext.xml:

    
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <import resource="spring-dao.xml"/>
    
        <bean id="userMapper" class="xyz.luck1y.mapper.UserMapperImpl">
            <property name="sqlSession" ref="sqlSession"/>
        bean>
    beans>
    
  4. 测试

    第一种没单独写applicationContext.xml配置文件的

    @Test
    public void test() throws IOException {
    
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-dao.xml");
        UserMapper userMapper = context.getBean("userMapper", UserMapper.class);
        for (User user : userMapper.selectUser()) {
            System.out.println(user);
        }
    }
    

    第二种:注入实现类

    @Test
    public void test() throws IOException {
    
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserMapper userMapper = context.getBean("userMapper", UserMapper.class);
        for (User user : userMapper.selectUser()) {
            System.out.println(user);
        }
    }
    
  5. 结果:

    Spring整合MyBatis、声明式事务_第1张图片

MyBatis-Spring 整合方式二

方式一中国我们需要在xml中注册以下内容:


<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
    
    <constructor-arg index="0" ref="sqlSessionFactory"/>
bean>

方式二就不用注册这个SqlSessionTemplate,直接在实现类中继承一个类:SqlSessionDaoSupport

package xyz.luck1y.mapper;


import org.mybatis.spring.support.SqlSessionDaoSupport;
import xyz.luck1y.pojo.User;

import java.util.List;

public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper {
    @Override
    public List<User> selectUser() {
        return getSqlSession().getMapper(UserMapper.class).selectUser();
    }
}

进入SqlSessionDaoSupport类,可以看到这个类就是把方式一的内容封装了一下,因此,我们就不用再xml中注册sqlSessionTemplate

Spring整合MyBatis、声明式事务_第2张图片

将这个实现类注册到容器中,只需要将spring-dao.xml中配置的sqlSessionFactory注入即可:

<bean id="userMapper2" class="xyz.luck1y.mapper.UserMapperImpl2">
    <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
bean>

使用方式二,相当于将中间的一步省略掉了,其实是被SqlSessionDaoSupport封装起来了。

声明式事务

事务回顾

  • 把一组业务当成一个业务来做,要么都成功,要么都失败!
  • 事务在项目开发中,十分重要,涉及到数据的一致性问题。
  • 确保完整性和一致性
  • 事物的ACID原则:
    • 原子性、一致性、隔离性、持久性

Spring中的事务管理

一个使用 MyBatis-Spring 的其中一个主要原因是它允许 MyBatis 参与到 Spring 的事务管理中。而不是给 MyBatis 创建一个新的专用事务管理器,MyBatis-Spring 借助了 Spring 中的 DataSourceTransactionManager 来实现事务管理。

一旦配置好了 Spring 的事务管理器,你就可以在 Spring 中按你平时的方式来配置事务。并且支持 @Transactional 注解和 AOP 风格的配置。在事务处理期间,一个单独的 SqlSession 对象将会被创建和使用。当事务完成时,这个 session 会以合适的方式提交或回滚。

事务配置好了以后,MyBatis-Spring 将会透明地管理事务。这样在你的 DAO 类中就不需要额外的代码了。

在Spring中的事务管理,分为以下两类

  • 声明式事务:AOP
  • 编程式事务:在代码中进行事务的管理

我们主要学习声明式事务:因为它在不改变原有代码的基础上,使用AOP的方法完成了事务的声明。

在Spring的配置文件中,配置声明式事务


<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
bean>



<tx:advice id="txAdvice" transaction-manager="transactionManager">
    
    
    <tx:attributes>
        
        
        
        
        
        <tx:method name="*"/>
    tx:attributes>
tx:advice>


<aop:config>
    <aop:pointcut id="txPointCut" expression="execution(* xyz.luck1y.mapper.*.*(..))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
aop:config>

接口:

package xyz.luck1y.mapper;

import xyz.luck1y.pojo.User;

import java.util.List;

public interface UserMapper {
    List<User> selectUser();

    // 添加一个用户
    public int addUser(User user);

    // 删除一个用户
    public int deleteUser(@Param("id") int id);
}

mapper.xml

注意:这里我们故意写错了一条语句,用来测试事务

deletes from mybatis.user where id=#{id}


DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="xyz.luck1y.mapper.UserMapper">
    <select id="selectUser" resultType="user">
        select * from mybatis.user
    select>

    <insert id="addUser" parameterType="user">
        insert into mybatis.user (id, name, pwd) VALUES (#{id}, #{name}, #{pwd})
    insert>

    <delete id="deleteUser" parameterType="int">
        
        deletes from mybatis.user where id=#{id}
    delete>
mapper>

实现类:

package xyz.luck1y.mapper;

import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import xyz.luck1y.pojo.User;

import java.util.List;

public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper {
    @Override
    public List<User> selectUser() {

        User user = new User(8, "小王", "1234141");

        UserMapper mapper = getSqlSession().getMapper(UserMapper.class);
        mapper.addUser(user);
        mapper.deleteUser(8);
        return mapper.selectUser();
    }

    @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);
    }
}

测试类:

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import xyz.luck1y.mapper.UserMapper;
import xyz.luck1y.pojo.User;

import java.util.List;

public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserMapper userMapper = context.getBean("userMapper", UserMapper.class);
        List<User> users = userMapper.selectUser();
        for (User user : users) {
            System.out.println(user);
        }
    }
}

初始表:

Spring整合MyBatis、声明式事务_第3张图片

关闭事务,执行测试程序:可以插入成功,并且删除也成功

Spring整合MyBatis、声明式事务_第4张图片

开启事务,还原表状态,执行测试程序,表的内容并没有变化:

Spring整合MyBatis、声明式事务_第5张图片

说明事务开启后,两个语句一起都失效了,即一条错误语句导致所有语句都失效,将错误语句改正,并且为了看到结果,增加8号,删除7号,测试:

Spring整合MyBatis、声明式事务_第6张图片

即如果我们没有开启事务,那么插入新用户8号会执行成功,如果我们开启了事务,那么插入和删除都不会成功。

综上所述:

如果不配置事务,会存在数据提交不一致的情况,后果很严重~

事务在项目的开发中十分重要,涉及到数据的一致性和完整性问题。

另外,如果我们不在Spring中配置声明式事务的话,就需要在代码中进行编程式事务的配置。

你可能感兴趣的:(Spring学习,spring,mybatis,java)