Mybatis-Spring

Mybatis-Spring

版本关系图

image-20221216193409235

当前环境

  • JDK8
  • Mybatis-Spring 2.1.0
  • Mybatis 3.5.11
  • Log4j 1.2.17
  • lombok 1.18.24
  • Spring Framework 5.3.20
  • Dbcp 2.9.0

🌈参考文档

Spring+Mybatis一起使用需要在Spring应用上下中定义至少两样东西

  • SqlSessionFactory
  • 至少一个数据映射器类

大致注册流程

image-20221217135747395

Mybatis ->Mybatis-Spring

image-20221217160208806

DataSource

  • db.properties
jdbc.password=root
jdbc.username=root
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mybatis_demo
jdbc.maxTotal=30
jdbc.maxIdle=10
jdbc.initialSize=5
  • 配置文件配置数据源
<!-- 读取数据源配置信息-->
<context:property-placeholder location="db.properties"/>
<!-- 配置Dbcp数据源-->
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="maxTotal" value="${jdbc.maxTotal}"/>
<property name="maxIdle" value="${jdbc.maxIdle}"/>
<property name="initialSize" value="${jdbc.initialSize}"/>
</bean>
  • 注解配置数据源
//TODO

SqlSessionFactoryBean

SqlSessionFactoryBean属性

  • DataSource

    • image-20221217113148838
    • 唯一必要属性,用于JDBC的DataSource。
  • configLocation(设置Mybatis基础配置文件)

    • 用来指定Mybatis的Xml配置文件路径
    • 如果Mybatis的Xml配置文件中配置了都会被忽略
  • mapperLocations(设置映射器配置文件)

    • 如果Mybatis在映射器类对应的路径下找不到与之对应的映射器XML文件,也需要配置文件。

      1. 手动在Mybatis的Xml配置文件中的部分指定XML文件的类路径。

      mybatis-config.xml

      image-20221217114528315

      1. 在设置工厂Bean的mapperLocations属性中。

      applicationContext.xml

      image-20221217114638223

  • transactonFactoryClass

    • 容器管理事务
  • databaseIdProvider

    • 多个数据库
  • image-20221217115313847

获取SqlSessionFactory

在基础的 MyBatis 用法中,是通过 SqlSessionFactoryBuilder 来创建 SqlSessionFactory 的。而在 MyBatis-Spring 中,则使用 SqlSessionFactoryBean 来创建。

SqlSessionFactoryBean实现了FactoryBean接口。

🌈FactoryBean接口详情

通常,在 MyBatis-Spring 中,你不需要直接使用 SqlSessionFactoryBean 或对应的 SqlSessionFactory。 相反,session 的工厂 bean 将会被注入到 MapperFactoryBean 或其它继承于 SqlSessionDaoSupport 的 DAO(Data Access Object,数据访问对象)中。

  • 配置文件配置
<!-- 配置SqlSessionFactory,SqlSessionFactoryBean需要诸如一个DataSource来创建SqlSessionFactory(有点类似于SqlSessionFactoryBuilder)-->
<!-- SqlSessionFactory的作用域是应用域-->
<!-- 可以理解为SqlSessionFactoryBean拿着DataSource去生成SqlSessionFactory-->
<!-- 创建的不是SqlSessionFactoryBean本身,而是SqlSessionFactory.getObject()方法的返回结果-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<!-- 会加载原来的Mybatis基础配置,基础配置主要指的是 <settings> 或 <typeAliases> 元素。-->
<property name="configLocation" value="mybatis-config.xml"/>
<!-- 加载Mapper映射文件-->
<property name="mapperLocations" value="StudentMapper.xml"/>
<!-- 事务管理-->
<property name="transactionFactory" value="XXX"
</bean>
  • 注解配置
//TODO

注意:SqlSessionFactory需要一个DataSource,这可以是任意的DataSource,只需要和配置其他的Spring数据库连接一样配置就可以了。

事务

Mybatis-Spring接住了Spring中的DataSourceTransactionManager来实现事务管理。在事务处理期间,一个单独的 SqlSession 对象将会被创建和使用。当事务完成时,这个SqlSession会以合适的方式提交或回滚。

标准配置

事务管理器需要注入一个数据源

  • Xml配置
<!-- 配置事务管理-->
<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());
}
}

这里的数据源必须与SqlSessionFactoryBean中注入的数据源一致。

注意,如果你想使用由容器管理的事务,而不想使用 Spring 的事务管理,你就不能配置任何的 Spring 事务管理器。并必须配置 SqlSessionFactoryBean 以使用基本的 MyBatis 的 ManagedTransactionFactory

编程式事务管理

MyBatis 的 SqlSession 提供几个方法来在代码中处理事务。但是当使用 MyBatis-Spring 时,你的 bean 将会注入由 Spring 管理的 SqlSession 或映射器。也就是说,Spring 总是为你处理了事务。

不能在 Spring 管理的 SqlSession 上调用 SqlSession.commit()SqlSession.rollback()SqlSession.close() 方法。如果这样做了,就会抛出 UnsupportedOperationException 异常。在使用注入的映射器时,这些方法也不会暴露出来。

无论 JDBC 连接是否设置为自动提交,调用 SqlSession 数据方法或在 Spring 事务之外调用任何在映射器中方法,事务都将会自动被提交。

也可以使用PlatfromTransactionManager手工管理事务。🌈示例代码

使用SqlSession

SqlSessionTeamplate

SqlSessionTemplate 是 MyBatis-Spring 的核心。作为 SqlSession 的一个实现,这意味着可以使用它无缝代替你代码中已经在使用的 SqlSessionSqlSessionTemplate 是线程安全的,可以被多个 DAO 或映射器所共享使用。

可以使用 SqlSessionFactory 作为构造方法的参数来创建 SqlSessionTemplate 对象。

SqlSessionTemplate 是 MyBatis-Spring 的核心。作为 SqlSession 的一个实现,这意味着可以使用它无缝代替你代码中已经在使用的 SqlSessionSqlSessionTemplate 是线程安全的,可以被多个 DAO 或映射器所共享使用。

当调用 SQL 方法时(包括由 getMapper() 方法返回的映射器中的方法),SqlSessionTemplate 将会保证使用的 SqlSession 与当前 Spring 的事务相关。 此外,它管理 session 的生命周期,包含必要的关闭、提交或回滚操作。另外,它也负责将 MyBatis 的异常翻译成 Spring 中的 DataAccessExceptions

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

  • Xml配置
<!-- 容器中放入SqlSessionTemplate,注入一个SqlSessionFactory用来管理SqlSession的创建关闭,事务的回滚和提交-->
<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory"/>
</bean>
  • 注解配置
@Configuration
public class MyBatisConfig {
@Bean
public SqlSessionTemplate sqlSession() throws Exception {
return new SqlSessionTemplate(sqlSessionFactory());
}
}

测试

这里的sqlSessionTemplate相当于SqlSession,SqlSessionTemplate完成了对SqlSession的创建关闭,事物的回滚提交的管理。

@Autowired
private SqlSessionTemplate sqlSessionTemplate;
@Test
public void testSqlSessionTemplate(){
final StudentMapper mapper = sqlSessionTemplate.getMapper(StudentMapper.class);
final Student student = mapper.selectOne(1L);
System.out.println(student.toString());
}

这里如果调用SqlSessionTemplate.commit()方法会直接报错,验证了上面的说法。

image-20221217131444605

SqlSessionTemplate还可以批量创建SqlSession连接

<!-- 容器中放入SqlSessionTemplate,注入一个SqlSessionFactory用来管理SqlSession的创建关闭,事务的回滚和提交-->
<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory"/>
<constructor-arg index="1" value="BATCH"/>
</bean>

这种配置的弊端在于,当调用这个方法时,不能存在使用不同 ExecutorType 的进行中的事务。要么确保对不同 ExecutorTypeSqlSessionTemplate 的调用处在不同的事务中,要么完全不使用事务。(摸不到头脑😑)

SqlSessoinDaoSupport

🌈详情

可以调用getSqlsession()来获取一个SqlSession连接,如果你需要在 DAO 中做其它非 MyBatis 的工作或需要一个非抽象的实现类,那么这个类就很有用了。

映射器

数据访问对象(DAO,Data Access Object)

定义如下Mapper接口

package cn.pickle.mapper;
import cn.pickle.entity.Student;
/**
* @author Pickle
* @version V1.0
* @date 2022/12/15 22:50
*/
public interface StudentMapper {
Student selectOne(Long id);
}

通过注解来指定 SQL 语句,但是也可以使用 MyBatis 映射器的 XML 配置文件。

StudentMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.pickle.mapper.StudentMapper">
<cache/>
<select id="selectOne" resultType="cn.pickle.entity.Student">
Select * from mybatis_demo.student where id = #{id};
</select>
</mapper>
  • 配置文件放入容器

注册映射器

如果映射器接口 StudentMapper 在相同的类路径下有对应的 MyBatis XML 映射器配置文件,将会被 MapperFactoryBean 自动解析。不需要在 MyBatis 配置文件中显式配置映射器,除非映射器配置文件与接口类不在同一个类路径下。

MapperFactoryBean注册Mapper接口

  • 配置文件注册
<!-- 将StudentMapper接口放到Spring容器中-->
<!-- MapperFactoryBean会负责SqlSession的创建和关闭-->
<!-- SqlSession会getMapper(),来获取对应的mapper中的方法-->
<!-- 如果使用了 Spring 的事务功能,那么当事务完成时,session 将会被提交或回滚。最终任何异常都会被转换成 Spring 的 DataAccessException 异常。-->
<!-- 可以理解为MapperFactoryBean拿着SqlSessionFactory和对应的Mapper全限定名去生成相应的Mapper-->
<bean id="studentMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="cn.pickle.mapper.StudentMapper"/>
<!-- <property name="sqlSessionFactory" ref="sqlSessionFactory"/> -->
<property name="sqlSessionTemplate" ref="sqlSessionTemplate"/>
</bean>
  • 注解注册
@Configuration
public class MyBatisConfig {
@Bean
public MapperFactoryBean<UserMapper> studentMapper() throws Exception {
MapperFactoryBean<StudentMapper> factoryBean = new MapperFactoryBean<>(StudentMapper.class);
factoryBean.setSqlSessionFactory(sqlSessionFactory());
return factoryBean;
}
}

注意 MapperFactoryBean 需要配置一个 SqlSessionFactorySqlSessionTemplate。它们可以分别通过 sqlSessionFactorysqlSessionTemplate 属性来进行设置。 如果两者都被设置,SqlSessionFactory 将被忽略。由于 SqlSessionTemplate 已经设置了一个 session 工厂,MapperFactoryBean 将使用那个工厂。

发现映射器

不再需要手动的一个个注册映射器

  • < mybatis:scan >
<!-- 自动注册映射器-->
<mybatis:scan base-package="cn.pickle.mapper"/>

因为自动发现也是通过注入SqlSessionFactory或者SqlSessionTemplate实现相应的Mapper的,所以也可以通过template-ref或者factory-ref指定需要的Bean;

image-20221217161548968

如果没有使用注解显式指定名称,将会使用映射器的首字母小写非全限定类名作为名称。

  • @MapperScan

这个注解具有与之前见过的 <mybatis:scan/> 元素一样的工作方式。它也可以通过 markerInterfaceannotationClass 属性设置标记接口或注解类。 通过配置 sqlSessionFactorysqlSessionTemplate 属性,你还能指定一个 SqlSessionFactorySqlSessionTemplate

从 2.0.4 起,如果 basePackageClassesbasePackages 没有定义, 扫描将基于声明这个注解的类所在的包。

  • MapperScannerConfigurer

🌈详情

posted @   破忒头头  阅读(73)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗
点击右上角即可分享
微信分享提示