Spring整合MyBatis之SqlSessionFactory对象的产生
目录
- 为什么 `MyBatis` 要和 `Spring` 整合
- `Spring` 整合 `MyBatis`
- `Maven` 依赖
- 创建 `Spring` 配置文件
- 创建 `MyBatis` 配置文件
- 创建 `Mapper` 映射文件
- 创建测试类
- `SqlSessionFactory` 对象的产生
- `SqlSessionFactoryBean` 源码
- `FactoryBean` 接口
- `InitializingBean` 接口
- `getObject()` 和 `afterPropertiesSet()` 的实现
- 总结
为什么 MyBatis
要和 Spring
整合
Spring
会帮助我们管理bean
:省去我们对SqlSessionFactory、SqlSession、Mapper
映射器这些核心对象(bean
)的创建,不需要我们手工去创建了,Spring
会通过IOC
容器来帮我们管理这些对象Spring
使用xxxTemplate
封装了方法:Spring
整合MyBatis
,它为我们提供了一个xxxTemplate
方法,方便我们去调用
Spring
整合 MyBatis
Maven
依赖
<dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>1.3.2</version>
</dependency>
创建 Spring
配置文件
<?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 http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"><bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/test"/><property name="username" value="root"/><property name="password" value="123abc"/></bean><bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="configLocation" value="classpath:/resource/cfg.xml"/><property name="dataSource" ref="dataSource"/></bean><bean id="mapperFactoryBean" class="org.mybatis.spring.mapper.MapperFactoryBean"><property name="mapperInterface" value="net.itaem.dao.PersonDao"/><property name="sqlSessionFactory" ref="sqlSessionFactory"/></bean>
</beans>
创建 MyBatis
配置文件
<?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> <!-- mapping 文件路径配置 --> <mappers> <mapper resource="resource/PersonMapper.xml" /> </mappers>
</configuration>
创建 Mapper
映射文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://www.mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="net.itaem.dao.PersonDao" ><resultMap id="resultMap" type="net.itaem.po.Person" ><result column="id" property="id" jdbcType="CHAR" /><result column="name" property="name" jdbcType="CHAR" /></resultMap><!--添加--> <insert id="save" parameterType="net.itaem.po.Person">insert into person(id,name) value(#{id,jdbcType=CHAR},#{name,jdbcType=CHAR})</insert><!--查询--><select id="query" resultMap="resultMap">select * from person</select><!--删除--><delete id="delete" parameterType="java.lang.String">delete from person where id=#{id,jdbcType=CHAR}</delete>
</mapper>
创建测试类
public class SpringTest {public static void main(String[] args) {ApplicationContext context = new ClassPathXmlApplicationContext("resource/applicationContext.xml");PersonDao personDao = (PersonDao) context.getBean("personDao");Person person = new Person("12","Fighter168");personDao.save(person);}
}
通过上面的比较,我们发现,在 Spring
中使用 MyBatis
是相当方便的,不需要我们去管理 SqlSessionFactory
以及 SqlSession
的对象(bean
)
SqlSessionFactory
对象的产生
我们已经了解到,MyBatis
的使用离不开 SqlSessionFactory、SqlSession、Mapper
这三大对象。这三大对象是如何被创建的呢?我们先看 SqlSessionFactory
对象的产生
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="configLocation" value="classpath:/resource/cfg.xml"/><property name="dataSource" ref="dataSource"/>
</bean>
我们已经在 applicationContext.xml
中配置了 sqlSessionFactoryBean
,通过名称我们便可以大概了解到该 bean
就是用来为我们创建 sqlSessionFactory
对象的类
SqlSessionFactoryBean
源码
在 mybatis-spring-1.3.2.jar
包中找到 SqlSessionFactoryBean
类,源码如下
public class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ApplicationEvent> {private Resource configLocation;private Configuration configuration;private Resource[] mapperLocations;private DataSource dataSource;private TransactionFactory transactionFactory;private Properties configurationProperties;private SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();private SqlSessionFactory sqlSessionFactory;private boolean failFast;private Interceptor[] plugins;private TypeHandler<?>[] typeHandlers;private String typeHandlersPackage;private Class<?>[] typeAliases;private String typeAliasesPackage;private Class<?> typeAliasesSuperType;......
}
我们看到该类实现了一个 FactoryBean、InitializingBean
的接口,下面分析这两个接口
FactoryBean
接口
分析 FactoryBean
接口,我们看到该接口共有三个方法需要实现,此处我们重点来关注一下 getObject()
方法
public interface FactoryBean<T> {// 该方法用来获取bean,即从Spring IOC容器中获取创建的bean,会调用到该方法@NullableT getObject() throws Exception;@NullableClass<?> getObjectType();default boolean isSingleton() {return true;}
}
FactoryBean
接口的作用:首先它是一个 bean
,但又不仅仅是一个 bean
。它是一个能生产或修饰对象生成的工厂 bean
,类似于设计模式中的工厂模式和装饰器模式。它能在需要的时候生产一个 bean
,且不仅仅限于它自身,它能返回任何 bean
的实例
FactoryBean
接口的详细分析:https://www.cnblogs.com/guitu18/p/11284894.html
InitializingBean
接口
在源码中,我们能够看到该接口有一个 afterPropertiesSet()
方法需要实现
public interface InitializingBean {void afterPropertiesSet() throws Exception;
}
该方法的作用:在 bean
的实例化和 bean
的属性填充完成后,执行的一些操作,该方法由 BeanFactory
调用。即创建工厂类的时候,一定会调用这个方法
getObject()
和 afterPropertiesSet()
的实现
介绍完这两个接口,我们再来看看 getObject()
方法和 afterPropertiesSet()
方法在 SqlSessionFactoryBean
类中的具体实现过程
public class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ApplicationEvent> {// 其他属性、方法 省略,仅展示要分析的源码 ......@Overridepublic SqlSessionFactory getObject() throws Exception {if (this.sqlSessionFactory == null) {// 1.第一步afterPropertiesSet();}return this.sqlSessionFactory;}@Overridepublic void afterPropertiesSet() throws Exception {notNull(dataSource, "Property 'dataSource' is required");notNull(sqlSessionFactoryBuilder, "Property 'sqlSessionFactoryBuilder' is required");state((configuration == null && configLocation == null) || !(configuration != null && configLocation != null),"Property 'configuration' and 'configLocation' can not specified with together");// 2.第二步this.sqlSessionFactory = buildSqlSessionFactory();}protected SqlSessionFactory buildSqlSessionFactory() throws IOException {Configuration configuration;// 3.第三步:XMLConfigBuilder 用来读取配置的 xmlConfigXMLConfigBuilder xmlConfigBuilder = null;if (this.configuration != null) {configuration = this.configuration;if (configuration.getVariables() == null) {configuration.setVariables(this.configurationProperties);} else if (this.configurationProperties != null) {configuration.getVariables().putAll(this.configurationProperties);}} else if (this.configLocation != null) {xmlConfigBuilder = new XMLConfigBuilder(this.configLocation.getInputStream(), null, this.configurationProperties);configuration = xmlConfigBuilder.getConfiguration();} else {// 省略部分判断代码......}if (xmlConfigBuilder != null) {try {// 4.执行 xmlConfigBuilder.parse()方法,此处已经走入到 mybatis 源码部分,已经是MyBatis的执行流程了。xmlConfigBuilder.parse();if (LOGGER.isDebugEnabled()) {LOGGER.debug("Parsed configuration file: '" + this.configLocation + "'");}} catch (Exception ex) {throw new NestedIOException("Failed to parse config resource: " + this.configLocation, ex);} finally {ErrorContext.instance().reset();}}if (!isEmpty(this.mapperLocations)) {for (Resource mapperLocation : this.mapperLocations) {if (mapperLocation == null) {continue;}try {// 5.解析 XMLMapper 映射器XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(mapperLocation.getInputStream(),configuration, mapperLocation.toString(), configuration.getSqlFragments());// 6.调用 xmlMapperBuilder.parse()方法,跳转到MyBatis源码去解析 XMLMapper 配置xmlMapperBuilder.parse();} catch (Exception e) {throw new NestedIOException("Failed to parse mapping resource: '" + mapperLocation + "'", e);} finally {ErrorContext.instance().reset();}}} else {if (LOGGER.isDebugEnabled()) {LOGGER.debug("Property 'mapperLocations' was not specified or no matching resources found");}}// 7.通过sqlSessionFactoryBuilder.build()方法,创建一个sqlSessionFactoryreturn this.sqlSessionFactoryBuilder.build(configuration);}
}
build()
方法调用如下
public SqlSessionFactory build(Configuration config) {return new DefaultSqlSessionFactory(config);
}
DefaultSqlSessionFactory
类与 SqlSessionFactory
接口的关系
public class DefaultSqlSessionFactory implements SqlSessionFactory {private final Configuration configuration;public DefaultSqlSessionFactory(Configuration configuration) {this.configuration = configuration;}
}
通过如上代码分析,此处我们整理了一下,执行流程如下图所示
总结
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><property name="configLocation" value="classpath:/resource/cfg.xml"/><property name="dataSource" ref="dataSource"/>
</bean>
配置完上面这个,它便会在 Spring
容器时启动创建 SqlSessionFactoryBean
时,调用 getObject()
等一系列方法,将全局配置文件和 mapper
配置文件等一些列操作在上面源码中都已经完成。最后调用了一个 return this.sqlSessionFactoryBuilder.build(configuration);
返回了一个 DefaultSqlSessionFactory
对象。此时创建 SqlSessionFactory
对象的任务就算完成了
Spring整合MyBatis之SqlSessionFactory对象的产生相关推荐
- Spring整合Mybatis之DAO层、Service层开发
3. Spring整合Mybatis编程DAO层开发 1. 项目引入相关依赖spring mybatis mysql mybatis-spring druid2. 编写spring.xml整合:spr ...
- Spring整合MyBatis总结
整合原理 MyBatis操作数据库,对数据库进行CRUD(增.删.改.查)操作时,实际原理是通过SqlSessionFactory对象---->产生SqlSession---->利用Sql ...
- Spring整合Mybatis之注解方式,(注解整合Junit)
Spring整合Mybatis之注解方式 我有一篇博客详细写了我自己使用xml的方法Spring整合MyBatis,现在我就把核心配置文件中的每个bean的配置使用注解的方式实现 注解整合MyBati ...
- spring 整合 mybatis 中数据源的几种配置方式
因为spring 整合mybatis的过程中, 有好几种整合方式,尤其是数据源那块,经常看到不一样的配置方式,总感觉有点乱,所以今天有空总结下. 一.采用org.mybatis.spring.mapp ...
- Spring 整合 Mybatis
数据库环境 // 创建mybatis数据库 create database mybatis;use mybatis // 创建teacher表 create table teacher(id int ...
- 【Java从0到架构师】Spring - 整合 MyBatis
整合 MyBatis 整合 MyBatis - 依赖 整合 MyBatis - 数据源 整合 MyBatis - SqlSessionFactoryBean 整合 MyBatis - MapperSc ...
- Spring——Spring整合MyBatis
文章目录: 1.写在前面 2.实现步骤 2.1 项目的大体框架 2.2 使用Navicat在数据库中创建一张表student2 2.3 在pom.xml文件中加入maven依赖 2.4 编写实体类St ...
- Spring 整合 Mybatis - 二(切面、事务管理)
紧接着上篇<Spring 整合 Mybatis - 一(基础)>,介绍Spring 整合 Mybatis的切面.事务管理. 1 增加切面aop功能 1.1 spring.xml sprin ...
- Spring 整合 Mybatis 原理
目录 Mybatis的基本工作原理 分析需要解决的问题 Spring中Bean的产生过程 解决问题 解决方案 FactoryBean Import 总结 优化 Mybatis的基本工作原理 在 Myb ...
- Spring整合Mybatis注解方式
Spring整合Mybatis(注解方式) 目录 Spring整合Mybatis(注解方式) 环境准备 纯注解方式 配置类具体内容 测试类具体内容 环境准备 jar包: Spring所需依赖:spri ...
最新文章
- GCC 连接器、链接标准库 gcc -l、链接手动创建库(指定目录的库 gcc -L)
- Linux下获取usb视频设备vendor id和product id的8种方法
- 位运算详解+竞赛常见用法总结
- js setTimeout()的使用
- java实现迷宫算法--转
- 这 6 个 Spring Boot 项目够经典
- linux 怎么重装libaprutil,Apache安装出错_cannot install `libaprutil-1.la' to a directory
- Knight Moves
- vs窗体 oracle,VS2010连接oracle数据库的简单例子
- 【剑指offer】面试题04:二维数组中的查找(java)
- power bulider 9.0 如何将sql语句查询的值返回给变量_SQL—你应该知道的子查询
- 6月全球浏览器份额之争:霸主IE份额持续降至54%
- linux 锐捷 dns,锐捷Linux
- matlab特征值分解
- SkeyeVSS综合安防监控Onvif、RTSP、GB28181视频云无插件直播点播解决方案之监控视频实时多屏预览
- 一个刚毕业的大学生在一个陌生的城市如何租房?
- SQL 2014新功能介绍系列3 - 备份还原篇
- Kerberos介绍(全)
- Premiere视频片段剪辑、添加音乐、添加字幕
- 基于Mini无人机与改进损失函数的YOLO V3的大豆幼苗自动计数系统V1.0-使用手册
热门文章
- 极客大学架构师训练营 系统架构 大型网站技术架构 维基百科、淘宝、新浪微博案例分析 第8课 听课总结
- 计算机博弈军旗程序,军棋机器人UCT算法及计算机博弈行为研究
- linux安装unity桌面环境,Ubuntu 14.04 server安装桌面环境
- mysql exporter怎么配置_prometheus mysqld_exporter监控mysql-5.7
- 113. 路径总和 II
- 多路复用增益,PASTA定理
- 华为鸿蒙巴龙麒麟,华为5G新机强势曝光:麒麟985+巴龙5000+鸿蒙系统,颜值性能炸裂...
- 图像条纹检测 python_光源在外观缺陷检测中的应用
- RDN:Residual Dense Network for Image Super-Resolution
- 频谱感知4:CCS硬合并中m-out-of-K准则下m与K的联合优化问题