0


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

在这里插入图片描述

💗wei_shuo的个人主页

💫wei_shuo的学习社区

🌐Hello World !

文章目录


▌Spring事务管理

事务(Transaction),一般是指要做的或所做的事情。在计算机

术语

中是指访问并可能更新数据库中各种

数据项

的一个程序

执行单元

。事务通常由

高级数据库

操纵语言或编程语言(如SQL,C++或Java)书写的

用户程序

的执行所引起,并用形如

begin transaction

end 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@NoArgsConstructorpublicclassUser{privateint id;private String name;private String pwd;}
  • UserMapper接口
package com.wei.Mapper;import com.wei.pojo.User;import java.util.List;publicinterfaceUserMapper{//查询用户public List<User>selectUser();//添加用户publicintaddUser(User user);//删除用户publicintdeleteUser(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接口--><mappernamespace="com.wei.Mapper.UserMapper"><!--select查询语句查询全部用户--><selectid="selectUser"resultType="com.wei.pojo.User">
        select * from mybatis.user;
    </select><insertid="addUser"parameterType="user">
        insert into mybatis.user (id, name, pwd) values (#{id}, #{name}, #{pwd});
    </insert><deleteid="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><!--标准日志工厂实现--><settingname="logImpl"value="LOG4J"/></settings><typeAliases><packagename="com.wei.pojo"/></typeAliases><!--环境配置--><environmentsdefault="development"><environmentid="development"><!--事物管理--><transactionManagertype="JDBC"/><dataSourcetype="POOLED"><propertyname="driver"value="com.mysql.cj.jdbc.Driver"/><propertyname="url"value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"/><propertyname="username"value="root"/><propertyname="password"value="root"/></dataSource></environment></environments></configuration>
  • Spring-dao.xml(配置、整合Mybatis)
<?xml version="1.0" encoding="UTF-8"?><beansxmlns="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的配置--><beanid="dataSource"class="org.springframework.jdbc.datasource.DriverManagerDataSource"><propertyname="driverClassName"value="com.mysql.cj.jdbc.Driver"/><propertyname="url"value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"/><propertyname="username"value="root"/><propertyname="password"value="root"/></bean><!--sqlSessionFactory--><beanid="sqlSessionFactory"class="org.mybatis.spring.SqlSessionFactoryBean"><!--配置数据源--><propertyname="dataSource"ref="dataSource"/><!--绑定Mybatis配置文件--><propertyname="configLocation"value="classpath:mybatis-config.xml"/><propertyname="mapperLocations"value="classpath:com/wei/Mapper/*.xml"/></bean><!--配置声明式事务--><!--要开启 Spring 的事务处理功能,在 Spring 的配置文件中创建一个 DataSourceTransactionManager 对象--><beanid="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><!--<property name="dataSource" ref="dataSource"/>--><constructor-argref="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;publicclassUserMapperImplextendsSqlSessionDaoSupportimplementsUserMapper{public List<User>selectUser(){

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

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

        mapper.addUser(user);
        mapper.deleteUser(5);return mapper.selectUser();}@OverridepublicintaddUser(User user){
        UserMapper mapper =getSqlSession().getMapper(UserMapper.class);return mapper.addUser(user);}@OverridepublicintdeleteUser(int id){
        UserMapper mapper =getSqlSession().getMapper(UserMapper.class);return mapper.deleteUser(1);}}

标准配置

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

DataSourceTransactionManager

对象:

<beanid="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><constructor-argref="dataSource"/></bean>
@ConfigurationpublicclassDataSourceConfig{@Beanpublic DataSourceTransactionManager transactionManager(){returnnewDataSourceTransactionManager(dataSource());}}

声明式事务

  • spring-dao.xml中配置事务
<?xml version="1.0" encoding="UTF-8"?><beansxmlns="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的配置--><beanid="dataSource"class="org.springframework.jdbc.datasource.DriverManagerDataSource"><propertyname="driverClassName"value="com.mysql.cj.jdbc.Driver"/><propertyname="url"value="jdbc:mysql://localhost:3306/mybatis?useSSL=true&amp;useUnicode=true&amp;characterEncoding=UTF-8"/><propertyname="username"value="root"/><propertyname="password"value="root"/></bean><!--sqlSessionFactory--><beanid="sqlSessionFactory"class="org.mybatis.spring.SqlSessionFactoryBean"><!--配置数据源--><propertyname="dataSource"ref="dataSource"/><!--绑定Mybatis配置文件--><propertyname="configLocation"value="classpath:mybatis-config.xml"/><propertyname="mapperLocations"value="classpath:com/wei/Mapper/*.xml"/></bean><!--配置声明式事务--><!--要开启 Spring 的事务处理功能,在 Spring 的配置文件中创建一个 DataSourceTransactionManager 对象--><beanid="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><!--<property name="dataSource" ref="dataSource"/>--><constructor-argref="dataSource"/></bean><!--结合AOP实现事务的织入--><!--配置事务通知advice--><tx:adviceid="txAdvice"transaction-manager="transactionManager"><!--给那些方法配置事务--><!--配置事务的传播特性:new propagation --><tx:attributes><tx:methodname="add"propagation="REQUIRED"/><tx:methodname="delete"propagation="REQUIRED"/><tx:methodname="update"propagation="REQUIRED"/><tx:methodname="select"propagation="REQUIRED"/><tx:methodname="query"read-only="true"/><!--所有方法配置事务--><tx:methodname="*"propagation="REQUIRED"/></tx:attributes></tx:advice><!--AOP:配置事务切入--><aop:config><!--配置事务切入点pointcut--><aop:pointcutid="txPointCut"expression="execution(* com.wei.Mapper.*.*(..))"/><!--配置事务顾问advisor切入,将事务txAdvice切入到txPointCut--><aop:advisoradvice-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;publicclassMyTest{@Testpublicvoidtest(){//解析beans.xml文件,生成管理相应的Bean对象,创建 Spring 的 IOC 容器
        ApplicationContext context =newClassPathXmlApplicationContext("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 =newSqlSessionFactoryBuilder().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  构造  sqlSessionpublicclassMybatisUtils{//提升作用域:定义SqlSessionFactory全局变量privatestatic 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 =newSqlSessionFactoryBuilder().build(inputStream);}catch(IOException e){
            e.printStackTrace();}}//既然有了 SqlSessionFactory,顾名思义,我们可以从中获得 SqlSession 的实例。//SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。//你可以通过 SqlSession 实例来直接执行已映射的 SQL 语句publicstatic SqlSession getSqlSession(){return sqlSessionFactory.openSession(true);//此处设置参数为true时,表示开启自动提交事物功能}}

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

在这里插入图片描述
在这里插入图片描述

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

SqlSessionFactoryBuilder(构造器)

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

SqlSessionFactory(工厂)

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

SqlSession(会话)

  • 连接到SqlSessionFactory(连接池)的一个请求
  • SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。
  • 使用完需要赶紧关闭,否则资源被占用 SqlSession.close()

🌼 结语:创作不易,如果觉得博主的文章赏心悦目,还请——

点赞

👍

收藏

⭐️

评论

📝

冲冲冲

🤞


在这里插入图片描述

标签: spring 数据库 java

本文转载自: https://blog.csdn.net/weixin_62765017/article/details/127954518
版权归原作者 wei_shuo 所有, 如有侵权,请联系我们删除。

“Spring事务管理 | 数据库连接池流程原理分析”的评论:

还没有评论