Spring事务管理 | 数据库连接池流程原理分析

这篇具有很好参考价值的文章主要介绍了Spring事务管理 | 数据库连接池流程原理分析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Spring事务管理 | 数据库连接池流程原理分析

💗wei_shuo的个人主页

💫wei_shuo的学习社区

🌐Hello World !


▌Spring事务管理

事务(Transaction),一般是指要做的或所做的事情。在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序执行单元。事务通常由高级数据库操纵语言或编程语言(如SQL,C++或Java)书写的用户程序的执行所引起,并用形如begin transactionend transaction语句(或函数调用)来界定。事务由事务开始(begin transaction)和事务结束(end transaction)之间执行的全体操作组成

概念:

例如:在关系数据库中,一个事务可以是一条SQL语句,一组SQL语句或整个程序

事务ACID原则:

  • 原子性(atomicity):一个事务是一个不可分割的工作单位,事务中包括的操作要么都做,要么都不做
  • 一致性(consistency):事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性密切相关
  • 隔离性(isolation):一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰
  • 持久性(durability):持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响
  • 声明式事务:

    通过AOP(面向切面)方式在方法前使用编程式事务的方法开启事务,通过注解或XML配置实现,在方法后提交或回滚。用配置文件的方法或注解方法(如:@Transactional)控制事务

  • 编程式事务:代码中进行事务管理

    手动开启、提交、回滚事务

环境搭建

  • User类
package com.wei.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private int id;
    private String name;
    private String pwd;
}
  • UserMapper接口
package com.wei.Mapper;

import com.wei.pojo.User;

import java.util.List;

public interface UserMapper {

    //查询用户
    public List<User> selectUser();

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

    //删除用户
    public int deleteUser(int id);
}
  • UserMapper.xml接口映射文件
<?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">

<!--namespace=绑定一个对应的Dao/Mapper接口-->
<mapper namespace="com.wei.Mapper.UserMapper">

    <!--select查询语句查询全部用户-->
    <select id="selectUser" resultType="com.wei.pojo.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>
  • mybatis-config.xml核心配置文件
    
<?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核心配置文件-->
<configuration>

    <!--引入外部配置文件-->
    <!--<properties resource="jdbc.properties"/>-->

    <settings>
        <!--标准日志工厂实现-->
        <setting name="logImpl" value="LOG4J"/>
    </settings>


    <typeAliases>
        <package name="com.wei.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=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>

</configuration>
  • Spring-dao.xml(配置、整合Mybatis)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:tx="http://www.springframework.org/schema/tx"

       xsi:schemaLocation="
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd

       http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd
        ">


    <!--DataSource:使用Spring的数据源替换Mybatis的配置-->
    <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=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </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/wei/Mapper/*.xml"/>
    </bean>


    <!--配置声明式事务-->

    <!--要开启 Spring 的事务处理功能,在 Spring 的配置文件中创建一个 DataSourceTransactionManager 对象-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--<property name="dataSource" ref="dataSource"/>-->
        <constructor-arg ref="dataSource" />
    </bean>

</beans>
  • applicationContext.xml(配置Spring框架所需的信息)
package com.wei.Mapper;

import com.wei.pojo.User;
import org.mybatis.spring.support.SqlSessionDaoSupport;

import java.util.List;

public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper{

    public List<User> selectUser(){

        User user = new User(5, "haha", "123456");

        UserMapper mapper = getSqlSession().getMapper(UserMapper.class);

        mapper.addUser(user);
        mapper.deleteUser(5);

        return mapper.selectUser();

    }

    @Override
    public int addUser(User user) {
        UserMapper mapper = getSqlSession().getMapper(UserMapper.class);
        return mapper.addUser(user);
    }

    @Override
    public int deleteUser(int id) {
        UserMapper mapper = getSqlSession().getMapper(UserMapper.class);
        return mapper.deleteUser(1);
    }
}

标准配置

要开启 Spring 的事务处理功能,在 Spring 的配置文件中创建一个 DataSourceTransactionManager 对象:

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<constructor-arg ref="dataSource" />
</bean>
@Configuration
public class DataSourceConfig {
@Bean
public DataSourceTransactionManager transactionManager() {
 return new DataSourceTransactionManager(dataSource());
}
}

声明式事务

  • 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"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"

       xsi:schemaLocation="
       http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd

       http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx.xsd

       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd
        ">


    <!--DataSource:使用Spring的数据源替换Mybatis的配置-->
    <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=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </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/wei/Mapper/*.xml"/>
    </bean>

    <!--配置声明式事务-->

    <!--要开启 Spring 的事务处理功能,在 Spring 的配置文件中创建一个 DataSourceTransactionManager 对象-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--<property name="dataSource" ref="dataSource"/>-->
        <constructor-arg ref="dataSource" />
    </bean>

    <!--结合AOP实现事务的织入-->
    <!--配置事务通知advice-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
    <!--给那些方法配置事务-->
        <!--配置事务的传播特性:new propagation -->
        <tx:attributes>
            <tx:method name="add" propagation="REQUIRED"/>
            <tx:method name="delete" propagation="REQUIRED"/>
            <tx:method name="update" propagation="REQUIRED"/>
            <tx:method name="select" propagation="REQUIRED"/>
            <tx:method name="query" read-only="true"/>
            <!--所有方法配置事务-->
            <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>

    <!--AOP:配置事务切入-->
    <aop:config>
        <!--配置事务切入点pointcut-->
        <aop:pointcut id="txPointCut" expression="execution(* com.wei.Mapper.*.*(..))"/>
        <!--配置事务顾问advisor切入,将事务txAdvice切入到txPointCut-->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>


    </aop:config>

</beans>
  • 测试类
import com.wei.Mapper.UserMapper;
import com.wei.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 test(){
        //解析beans.xml文件,生成管理相应的Bean对象,创建 Spring 的 IOC 容器
        ApplicationContext context = new ClassPathXmlApplicationContext("applicicationContext.xml");

        //getBean:参数即为Spring配置文件中的bean的id
        //从IOC容器中获取 bean 的实例
        UserMapper userMapper = context.getBean("userMapper", UserMapper.class);
        List<User> userList = userMapper.selectUser();

        for (User user : userList) {
            System.out.println(user);
        }


    }
}
  • isolation:隔离级别

  • no-rollback-for:不回滚

  • propagation:传播行为

    REQUIRED:支持当前事务,如果当前没有事务,就新建一个事务(默认)

    NESTED:支持当前事务,如果当前事务存在,则执行一个嵌套事务,如果当前没有事务,就新建一个事务

  • read-only:只读

  • rollback-for:回滚控制

  • timeout:过期时间

总结

配置事务原因:

  • 避免数据提交不一致
  • 事务涉及数据一致性和完整性问题

▌SqlSessionFactory

SqlSessionFactory是MyBatis的核心对象,用于初始化MyBatis,读取配置文件,创建SqlSession对象,SqlSessionFactory是全局对象,为保证其在应用中全局唯一,要使用static进行初始化

SqlSession是MyBatis操作数据库的核心对象,SqlSession使用JDBC方式与数据库交互,同时提供了数据表的CRUD(增删改查)对应的api方法

导入jar包

格式:

<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>x.x.x</version>
</dependency>
<!--mybatis-->
<dependency>
 <groupId>org.mybatis</groupId>
 <artifactId>mybatis</artifactId>
 <version>3.5.2</version>
</dependency>

XML 中构建 SqlSessionFactory

  • 每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心
  • SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 获得
  • 而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先配置的 Configuration 实例来构建出 SqlSessionFactory 实例
  • 获取sqlSessionFaction对象
String resource = "org/mybatis/example/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

获得 SqlSession 的实例

既然有了 SqlSessionFactory,顾名思义,我们可以从中获得 SqlSession 的实例。SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。你可以通过 SqlSession 实例来直接执行已映射的 SQL 语句

SqlSession sqlSession = sessionFactory.openSession(true);

代码实现

  • utils包下创建工具类MybatisUtils类
package com.wei.utils;

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 java.io.IOException;
import java.io.InputStream;

//sqlSessionFactory  构造  sqlSession
public class MybatisUtils {
	//提升作用域:定义SqlSessionFactory全局变量
    private static SqlSessionFactory sqlSessionFactory;
//静态代码块:执行优先级高于非静态的初始化块,它会在类初始化的时候执行一次,执行完成便销毁,它仅能初始化类变量,即static修饰的数据成员
    static {	
        try {
            //使用Mybatis第一步:获取sqlSessionFactory对象
            
            //定义核心配置文件
            String resource = "mybatis-config.xml";
            //通过IO流加载resource的mybatis-config.xml核心配置文件文件
            InputStream inputStream = Resources.getResourceAsStream(resource);
            //通过build加载inputStream
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //既然有了 SqlSessionFactory,顾名思义,我们可以从中获得 SqlSession 的实例。
    //SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。
    //你可以通过 SqlSession 实例来直接执行已映射的 SQL 语句
    public static SqlSession getSqlSession(){
        return sqlSessionFactory.openSession(true);		//此处设置参数为true时,表示开启自动提交事物功能
    }
}

▌作用域(Scope)和生命周期

Spring事务管理 | 数据库连接池流程原理分析
Spring事务管理 | 数据库连接池流程原理分析

所有代码中都遵循这种使用模式,可以保证所有数据库资源都能被正确地关闭

SqlSessionFactoryBuilder(构造器)

  • 一旦创建了 SqlSessionFactory,就不再需要它了
  • 局部变量

SqlSessionFactory(工厂)

  • SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例
  • 数据库连接池
  • SqlSessionFactory 的最佳作用域是应用作用域
  • 最简单的就是使用单例模式或者静态单例模式

SqlSession(会话)

  • 连接到SqlSessionFactory(连接池)的一个请求

  • SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。

  • 使用完需要赶紧关闭,否则资源被占用 SqlSession.close()


🌼 结语:创作不易,如果觉得博主的文章赏心悦目,还请——点赞👍收藏⭐️评论📝冲冲冲🤞


Spring事务管理 | 数据库连接池流程原理分析文章来源地址https://www.toymoban.com/news/detail-432641.html

到了这里,关于Spring事务管理 | 数据库连接池流程原理分析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【cfengDB】自己实现数据库第0节 ---整体介绍及事务管理层实现

    LearnProj 本文作为数工底层的项目CfengDB开始篇章,介绍开发缘由和实现思路 cfeng之前对数据库研究不深入,之前只是能够做到基本的SQL查询和基本的慢SQL优化,之前拿到数据库系统工程师证书还是只在业务上对于DB系统使用更深入,但是cfeng基于work的理解,当作为一个优秀的产

    2024年02月16日
    浏览(42)
  • 4、hive的使用示例详解-事务表、视图、物化视图、DDL(数据库、表以及分区)管理详细操作

    1、apache-hive-3.1.2简介及部署(三种部署方式-内嵌模式、本地模式和远程模式)及验证详解 2、hive相关概念详解–架构、读写文件机制、数据存储 3、hive的使用示例详解-建表、数据类型详解、内部外部表、分区表、分桶表 4、hive的使用示例详解-事务表、视图、物化视图、DDL

    2024年02月09日
    浏览(51)
  • Spring Boot+Atomikos进行多数据源的分布式事务管理详解和实例

    背景: 一直零散的使用着Spring Boot 的各种组件和特性,从未系统性的学习和总结,本次借着这个机会搞一波。共同学习,一起进步。哈哈 Atomikos是一个易用、可靠、开放源码的事务管理器,它可以用于管理分布式事务,尤其在微服务架构中非常实用。它支持JTA(Java Transacti

    2024年02月11日
    浏览(44)
  • Spring | 基于SpringBoot的多数据源实战 - 使用seata实现多数据源的全局事务管理

    在软件开发中, 多数据源 的应用越来越普遍,特别是在 微服务架构 和 业务模块化 的场景下。多数据源能够让不同的业务模块和微服务拥有各自独立的数据存储,大大提高了系统的灵活性和可维护性。本文将深入探讨多数据源的配置和实施,以及在 Spring Boot 环境下,如何通

    2024年02月07日
    浏览(60)
  • Spring 事务管理方案和事务管理器及事务控制的API

    目录 一、事务管理方案 1. 修改业务层代码 2. 测试 二、事务管理器 1. 简介 2. 在配置文件中引入约束 3. 进行事务配置 三、事务控制的API 1. PlatformTransactionManager接口 2. TransactionDefinition接口 3. TransactionStatus接口 往期专栏文章相关导读  1. Maven系列专栏文章 2. Mybatis系列专栏文

    2024年02月08日
    浏览(42)
  • spring事务管理详解和实例(事务传播机制、事务隔离级别)

    目录 1 理解spring事务 2 核心接口 2.1 事务管理器 2.1.1 JDBC事务 2.1.2 Hibernate事务 2.1.3 Java持久化API事务(JPA) 2.2 基本事务属性的定义 2.2.1 传播行为 2.2.2 隔离级别 2.2.3 只读 2.2.4 事务超时 2.2.5 回滚规则 2.3 事务状态 3 编程式事务 3.1 编程式和声明式事务的区别 3.2 如何实现编程式

    2024年02月06日
    浏览(43)
  • 【Spring】Spring的事务管理

    Spring的事务管理简化了传统的事务管理流程,并且在一定程度上减少了开发者的工作量。 1.1 事务管理的核心接口 在Spring的所有JAR包中包含一个名为Spring-tx-4.3.6.RELEASE的JAR包,该包就是Spring提供的用于事务管理的依赖包。在该JAR包的org.Springframework.transaction包中有3个接口文件:

    2024年02月03日
    浏览(96)
  • Spring 事务管理

    目录 1. 事务管理 1.1. Spring框架的事务支持模型的优势 1.1.1. 全局事务 1.1.2. 本地事务 1.1.3. Spring框架的一致化编程模型 1.2. 了解Spring框架的事务抽象(Transaction Abstraction) 1.2.1. Hibernate 事务设置 1.3. 用事务同步资源 1.3.1. 高级同步方式 1.3.2. 低级同步方式 1.3.3.TransactionAwareDataSo

    2024年02月13日
    浏览(46)
  • Spring之事务管理

    事务是数据库操作最基本单位,要么都成功,要么都失败。 原子性 一致性 隔离性 持久性。 Spring定义了7种传播行为: 传播属性 描述 REQUIRED 如果有事务在运行,当前的方法就在这个事务内运行,否则,就启动一个新的事务,并在自己的事务内运行 REQUIRED_NEW 当前的方法必须

    2024年02月13日
    浏览(67)
  • Spring的事务管理

    1、事务的回顾 【1】事务的定义 是数据库操作的最小工作单元,是作为单个逻辑工作单元执行的一系列操作,这些操作作为一个整体一起向系统提交,要么都执行、要么都不执行;事务是一组不可再分割的操作集合 【2】事务的ACID原则 事务具有4个基本特性:原子性、一致性

    2023年04月16日
    浏览(76)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包