MyBatis笔记
使用样例
// 只使用MyBatis
public static void main(String[] args) throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
try (
SqlSession sqlSession = sqlSessionFactory.openSession()
) {
AppUserMapper userMapper = sqlSession.getMapper(AppUserMapper.class);
String name = userMapper.getName(7);
// 使用user对象
System.out.println(name);
}
}
@Mapper
public interface AppUserMapper{
String getName(Integer id);
}
<?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="org.apache.test.mapper.AppUserMapper">
<select id="getName">
select name
from ap_user
where id = #{id}
</select>
</mapper>
启动流程
-
创建
SqlSessionFactory
-
在创建
SqlSessionFactory
的过程中,会初始化XMLConfigBuilder
(随便会初始化Configuration
)该对象会解析mybatis-config.xml 文件,并解析文件中的标签,保存标签中的属性,或创建标签对应的对象,所有的属性和对象均会被保存在Configuration
-
private void parseConfiguration(XNode root) { try { // 处理<properties>标签,定义KV信息供MyBatis使用 propertiesElement(root.evalNode("properties")); // 处理<settings>标签,MyBatis全局性的配置 Properties settings = settingsAsProperties(root.evalNode("settings")); loadCustomVfs(settings); // 处理Log loadCustomLogImpl(settings); // 处理<typeAliases>标签 typeAliasesElement(root.evalNode("typeAliases")); // 处理<plugins>标签 pluginElement(root.evalNode("plugins")); // 处理<objectFactory>标签 objectFactoryElement(root.evalNode("objectFactory")); // 处理<objectWrapperFactory>标签 objectWrapperFactoryElement(root.evalNode("objectWrapperFactory")); // 处理<reflectorFactory>标签 reflectorFactoryElement(root.evalNode("reflectorFactory")); // 处理settings的相关标签 settingsElement(settings); // 处理<environments>标签 environmentsElement(root.evalNode("environments")); // 处理<databaseIdProvider>标签 databaseIdProviderElement(root.evalNode("databaseIdProvider")); // 处理<typeHandlers>标签 typeHandlerElement(root.evalNode("typeHandlers")); // 处理<mappers>标签 mapperElement(root.evalNode("mappers")); } catch (Exception e) { throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e); } }
-
在解析的过程中,会创建的对象包括:
- TypeAliasRegistry;别名注册器,保存别名与类之间的关系。
- InterceptorChain:插件链,保存所有的插件,组成链条。
- ObjectFactory:用于创建对象。
- ObjectWrapperFactory:创建
ObjectWrapper
,用于简化对对象属性的访问。 - ReflectorFactory:获取Reflector(类信息的包装)。
- TransactionFactory:事务工厂
- DataSourceFactory:数据源工厂->有池化和无池化两种连接池。
- databaseIdProvider:确定当前数据库的类型(例如 MySQL、Oracle 或 PostgreSQL)。
- TypeHandlerRegistry:类型转换注册器,java类型与数据库类型间的转换。
- MapperRegistry:Mapper接口与它的创建工厂。实现mapper接口与Mapper.xml文件
-
使用流程
SqlSession sqlSession = sqlSessionFactory.openSession()
-
创建
Executor
对象,执行SQL语句的对象。- BatchExecutor:批量操作
- ReuseExecutor:可重用,相同SQL只会进行一次预处理
- SimpleExecutor:每次都会进行预编译
注意
:如果开启二级缓存,则会在创建的Executor
对象上在包一层,创建CachingExecutor
。 -
在Executor的基础上创建
DefaultSqlSession
对象- 包括select,update,delete,insert,commit,rollback等方法。
执行流程
AppUserMapper userMapper = sqlSession.getMapper(AppUserMapper.class)
- 通过
DefaultSqlSession
对象的getMapper方法,拿到AppUserMapper
接口的代理对象。- 最终来到
MapperRegistry
的getMapper方法,拿到MapperProxyFactory对象,通过该对象的newInstance()
方法,最后调用jdk的动态代理创建对象。 - 在
newInstance()
方法中,会创建MapperProxy对象,该对象是动态代理的真正对象。保存了接口的相关信息,如:代理的接口,接口的方法和Invoker(反射),sqlSession等;
- 最终来到
方法执行过程
String name = userMapper.getName(7);
sql执行前
-
会进入到代理对象
MapperProxy
的invoke()
方法中。在方法中,会根据传入的Method,获取该Method的MapperMethodInvoker
,(缓存中有,直接获取,没有就创建,并保存在缓存中)。- DefaultMethodInvoker:借助
MethodHandle
执行方法,有JVM提供支持,性能更高。 - PlainMethodInvoker:依赖MapperMethod执行方法。
MapperMethod
介绍:- 保存了sql语句相关信息,如具体sql语句,语句的类型等。
- 保存了接口方法的相关信息,如方法的返回值类型。
- DefaultMethodInvoker:借助
-
大部分情况会调用
MapperMethod
的execute()
方法。 -
通过SqlSession相关的select,update,delete,insert等方法,底层是Executor的相关方法。
-
创建StatementHandler,并为Sql语句设置参数。最后调用jdbc的Statement执行语句。
sql执行后
- insert,delete,update会返回一个数字,直接通过typeHandler转换即可。
- select:通过Executor的query方法,执行sql查询,处理各种复杂情况,如嵌套查询,多结果集查询,一二级缓存,延迟加载等。查询逻辑有
缓存中查
和数据库查
。 - 还是通过jdbc的Statement执行语句。结果在Statement对象中。
- 调用resultSetHandler对结果进行处理,包括创建结果集,处理嵌套,类型转换等。
MyBatis与Spring整合。
- 由自己提供
SqlSessionFactoryBean
,和SqlSessionFactory
差不多。 - 当有了
SqlSessionFactory
,就可以获得SqlSession,有了SqlSession就可以通过getMapper获得接口的代理类,这样我们的接口就交给Spring管理了。
MyBatis与SpringBoot整合。
由于SqlSessionFactoryBean
已经通过自动装配创建好了。
所有在使用时就只需要写Mapper.xml文件和具体接口。
标签:大体,对象,标签,印象,创建,MyBatis,root,evalNode From: https://www.cnblogs.com/strind/p/18301265