spring+mybatis的实现+声明式事务

spring+mybatis的实现+声明式事务

    • spring+mybatis的配置
    • 第一种方式
    • 第二种方式
    • 事务

spring+mybatis的配置

依赖

<dependencies>
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.2</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.21</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.1.10.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.1.10.RELEASE</version>
        </dependency>
        <!--Spring AOP事务-JDBC必须要引入这个依赖-->
        <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.2</version>
        </dependency>
    </dependencies>
    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.properties
                    **/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.properties
                    **/*.xml</include>
                </includes>
                <filtering>false</filtering>
            </resource>
        </resources>
    </build>

pojo实体类

package com.kai.pojo;

public class User {
     
    private int id;
    private String name;
    private String pwd;

    @Override
    public String toString() {
     
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", pwd='" + pwd + '\'' +
                '}';
    }

    public int getId() {
     
        return id;
    }

    public void setId(int id) {
     
        this.id = id;
    }

    public String getName() {
     
        return name;
    }

    public void setName(String name) {
     
        this.name = name;
    }

    public String getPwd() {
     
        return pwd;
    }

    public void setPwd(String pwd) {
     
        this.pwd = pwd;
    }
}

mybatis配置类

这里配置很少一般就是配置一下别名和设置,具体的配置在spring中进行

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

    <typeAliases>
        <package name="com.kai.pojo"/>
    </typeAliases>

</configuration>

这个xml文件可以当作spring管理mybatis配置的具体文件。

spring-dao.xml

<?xml version="1.0" encoding="UTF-8"?>
<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
        https://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/db3?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean>
<!-- 绑定数据源
注意:SqlSessionFactory需要一个 DataSource(数据源)。这可以是任意的 DataSource,
只需要和配置其它 Spring 数据库连接一样配置它就可以了。-->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <!--绑定mybatis的配置-->
        <property name="configLocation" value="classpath:mybatis-config.xml"/>
        <!--如果在这里写了mapper 就不需要再mybatis-config里面再写mapper位置-->
        <property name="mapperLocations" value="classpath:com/kai/dao/*.xml"/>
    </bean>

<!--SqlSessionTemplate没有set方法只能通过构造创建sqlSession-->
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
        <constructor-arg index="0" ref="sqlSessionFactory" />
    </bean>

</beans>

接口

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

UserMapper.xml 管理mybatis

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.kai.dao.UserMapper" >
    <select id="selectUser" resultType="user">
        select * from user
    </select>


</mapper>

第一种方式

application.xml 管理bean

<?xml version="1.0" encoding="UTF-8"?>
<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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
<!--    导入mybatis相关的配置-->
    <import resource="spring-dao.xml" />
    
    <bean id="UserMapperImp" class="com.kai.dao.UserMapperImp">
        <property name="sqlSessionTemplate" ref="sqlSession"/>
    </bean>

</beans>

UserMapperImp 实体类

package com.kai.dao;

import com.kai.pojo.User;
import org.mybatis.spring.SqlSessionTemplate;

import java.util.List;

public class UserMapperImp implements UserMapper {
     

    private SqlSessionTemplate sqlSessionTemplate;

    public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
     
        this.sqlSessionTemplate = sqlSessionTemplate;
    }

    public List<User> selectUser() {
     
        UserMapper mapper = sqlSessionTemplate.getMapper(UserMapper.class);
        List<User> users = mapper.selectUser();
        return users;
    }
}

具体实现流程

UserMapperImp的bean在application.xml中通过set方法注入,并给其属性sqlSessionTemplate赋值,sqlSessionTemplate的值通过spring-mybatis源码构造参数是sqlSessionFactory的构造方法创建,SqlSessionFactory通过spring-mybatis源码SqlSessionFactoryBean 创建并设置数据源和配置。这样整个的mybatis都被spring管理。

关于SqlSessionTemplate

SqlSessionTemplate 是 MyBatis-Spring 的核心。作为 SqlSession 的一个实现,这意味着可以使用它无缝代替你代码中已经在使用的 SqlSession。模板可以参与到 Spring 的事务管理中,并且由于其是线程安全的,可以供多个映射器类使用,你应该总是用 SqlSessionTemplate 来替换 MyBatis 默认的 DefaultSqlSession 实现。在同一应用程序中的不同类之间混杂使用可能会引起数据一致性的问题

测试

    //mybatis和spring结合使用
    @Test
    public void test2(){
     
        ApplicationContext Context = new ClassPathXmlApplicationContext("application.xml");
        UserMapperImp bean = Context.getBean("UserMapperImp",UserMapperImp.class);
        List<User> users = bean.selectUser();
        for (User user : users) {
     
            System.out.println(user);
        }
    }

第二种方式

上面的spring-dao.xml文件可以去掉SqlSessionTemplate的构造方法创建
spring+mybatis的实现+声明式事务_第1张图片

UserMapperImp2通过继承SqlSessionDaoSupport ,直接用getSqlSession()方法来获取SqlSession。

这样就又省略了SqlSessionTemplate的注入

package com.kai.dao;

import com.kai.pojo.User;
import org.apache.ibatis.session.SqlSession;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import org.springframework.dao.support.DaoSupport;

import java.util.List;

//第二种方法 可以省略SqlSessionTemplate的注入
public class UserMapperImp2 extends SqlSessionDaoSupport implements UserMapper {
     
    public List<User> selectUser() {
     
        //这种方法可以直接通过getSqlSession()方法来获取
        SqlSession sqlSession = getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> users = mapper.selectUser();
        return users;
    }
}

<?xml version="1.0" encoding="UTF-8"?>
<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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
<!--    导入mybatis相关的配置-->
    <import resource="spring-dao.xml" />

<!--第二种-->
    <bean id="UserMapperImp2" class="com.kai.dao.UserMapperImp2">
        <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
    </bean>

</beans>
    //mybatis和spring结合使用 第二种方式 省略了sqlSessionTemplate的创建和set注入
    @Test
    public void test3(){
     
        ApplicationContext Context = new ClassPathXmlApplicationContext("application.xml");
        UserMapperImp2 bean = Context.getBean("UserMapperImp2",UserMapperImp2.class);
        List<User> users = bean.selectUser();
        for (User user : users) {
     
            System.out.println(user);
        }
    }

事务

事务在项目开发过程非常重要,涉及到数据的一致性的问题,不容马虎! 事务管理是企业级应用程序开发中必备技术,用来确保数据的完整性和一致性。

事务就是把一系列的动作当成一个独立的工作单元,这些动作要么全部完成,要么全部不起作用。

1.事务四个属性ACID

  • 原子性(atomicity)
    事务是原子性操作,由一系列动作组成,事务的原子性确保动作要么全部完成,要么完全不起作用

  • 一致性(consistency)
    一旦所有事务动作完成,事务就要被提交。数据和资源处于一种满足业务规则的一致性状态中

  • 隔离性(isolation)
    可能多个事务会同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止数据损坏

  • 持久性(durability)
    事务一旦完成,无论系统发生什么错误,结果都不会受到影响。通常情况下,事务的结果被写到持久化存储器中

2.为什么需要配置事务?

如果不配置,就需要我们手动提交控制事务(编程式事务管理)
事务在项目开发过程非常重要,涉及到数据的一致性和完整性

3.spring在不同的事务管理API之上定义了一个抽象层,使得开发人员不必了解底层的事务管理API就可以使用Spring的事务管理机制。Spring支持编程式事务管理和声明式的事务管理。

编程式事务管理

  • 将事务管理代码嵌到业务方法中来控制事务的提交和回滚
  • 缺点:必须在每个事务操作业务逻辑中包含额外的事务管理代码

声明式事务管理

  • 一般情况下比编程式事务好用。
  • 将事务管理代码从业务方法中分离出来,以声明的方式来实现事务管理。
  • 将事务管理作为横切关注点,通过aop方法模块化。Spring中通过Spring AOP框架支持声明式事务管理。

头文件的约束tx和aop

xmlns:tx="http://www.springframework.org/schema/tx"

http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
       	xmlns:aop="http://www.springframework.org/schema/aop"
       
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd">
 <!--JDBC事务管理-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>

propagation传播

事务传播行为就是多个事务方法相互调用时,事务如何在这些方法间传播。spring支持7种事务传播行为:

  • requierd:如果当前没有事务,就新建一个事务,如果已存在一个事务中,加入到这个事务中,这是最常见的选择。

  • supports:支持当前事务,如果没有当前事务,就以非事务方法执行。

  • mandatory:使用当前事务,如果没有当前事务,就抛出异常。

  • required_new:新建事务,如果当前存在事务,把当前事务挂起。

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

  • never:以非事务方式执行操作,如果当前事务存在则抛出异常。

  • nested:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与propagation_required类似的操作

tx:method 标签内的方法都在同一个事务中,有一个出错了,其他方法就不会运行。

<!--绑定事务管理 配置事务通知 -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
<!--配置哪些方法使用什么样的事务,配置事务的传播特性-->
        <tx:attributes>
            <tx:method name="insert" propagation="REQUIRED"/>
            <tx:method name="updata" propagation="REQUIRED"/>
            <tx:method name="delete" propagation="REQUIRED"/>
            <tx:method name="query" read-only="true"/>
            <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>

    <!--配置aop织入事务-->
    <aop:config>
        <aop:pointcut id="txPointcut" expression="execution(* com.kai.dao.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
    </aop:config>

注:因为我们是使用aop(动态代理)+事务所以需要通过Mapper接口类调方法
测试

    //mybatis和spring结合使用 第二种方式 省略了sqlSessionTemplate的创建和set注入
    @Test
    public void test3(){
     
        ApplicationContext Context = new ClassPathXmlApplicationContext("application.xml");
        UserMapper bean =  Context.getBean("UserMapperImp2",UserMapper.class);
        List<User> users = bean.selectUser();
        for (User user : users) {
     
            System.out.println(user);
        }
    }

你可能感兴趣的:(SSM,mybatis,spring,mysql,aop)