编程语言
首页 > 编程语言> > Mybatis的使用与源码分析

Mybatis的使用与源码分析

作者:互联网

1.Mybatis整合到SpringBoot项目

1.1 引入依赖

如果使用最基础级mybatis,使用以下依赖:

<!-- mybatis依赖-->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>${mybatis.version}</version>
</dependency>

如果使用通用mapper,使用以下依赖:

<!-- 通用mapper依赖 -->
<dependency>
    <groupId>tk.mybatis</groupId>
    <artifactId>mapper-spring-boot-starter</artifactId>
    <version>${version}</version>
</dependency>

如果使用mybatis-plus,使用以下依赖:

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>${version}</version>
</dependency>

如果使用mybatis-plus插件生成代码,使用以下依赖:

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-generator</artifactId>
    <version>${version}</version>
</dependency>
<!-- 以下依赖与选择的代码模板引擎有关,不同引擎选择不同模板-->
<dependency>
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity-engine-core</artifactId>
    <version>${version}</version>
</dependency>

1.2 增加Config

@Configuration
public class MybatisConfig {

    @Value("${mybatis.mapper-locations}")
    private String mapperLocations;

    @Bean
    public SqlSessionFactoryBean configSqlSessionFactoryBean(DataSource dataSource) throws IOException {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
        // 时候输出mybatis相关日志
        configuration.setLogImpl(StdOutImpl.class);
        // 开启驼峰命名
        configuration.setMapUnderscoreToCamelCase(true);
        sqlSessionFactoryBean.setConfiguration(configuration);
        sqlSessionFactoryBean.setDataSource(dataSource);
        // 设置pageHelper分页插件
        PageHelper pageHelper = new PageHelper();
        Properties properties = new Properties();
     // 指定数据库方言
        properties.setProperty("dialect", dialect);
        pageHelper.setProperties(properties);
        sqlSessionFactoryBean.setPlugins(pageHelper);
        // 设置mapper.xml路径
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        sqlSessionFactoryBean.setMapperLocations(resolver.getResources(mapperLocations));// 设置mapper文件扫描路径
        return sqlSessionFactoryBean;
    }
}

2.Mybatis的核心流程

XML处理相关的类

一、XMLConfigBuilder用来解析mybatis的核心配置文件文件xml中的节点,然后封装到Configuration类中;
二、XMLMapperBuilder用来解析mybatis中Mapper的xml文件,获取到所有节点为<select>|<insert>|<update>|<delete>的节点,然后通过XMLStatementBuilder类来解析这些节点,最后通过MapperBuilderAssistant类来转成MappedStatment对象,添加到Configuration中。

2.1 SqlSessionFactoryBuilder

负责创建SqlSessionFactory。主要解析出MybatisConfig.xml中数据数据库连接信息和Mapper.xml文件,封装成MappedStatement对象。
org.apache.ibatis.session.SqlSessionFactoryBuilder#build
org.apache.ibatis.builder.xml.XMLConfigBuilder#parse
sqlSessionFactory1
org.apache.ibatis.builder.xml.XMLConfigBuilder#parseConfiguration
sqlSessionFactory2

2.2 SqlSessionFactory

负责创建SqlSession,并指定SqlSession的执行器,环境,事务管理器,事务提交机制。
org.apache.ibatis.session.defaults.DefaultSqlSessionFactory#openSession()
sqlSession1
org.apache.ibatis.session.defaults.DefaultSqlSessionFactory#openSessionFromDataSource
sqlSession2

2.3 SqlSession

1.负责调用getMapper方法生成代理对象,并执行对应的代理对象调用方法的具体sql语句
org.apache.ibatis.binding.MapperRegistry#getMapper
生成mapper代理类1
org.apache.ibatis.binding.MapperProxyFactory#newInstance
生成mappr代理类2

2.4 ParameterHandler

负责将用户传递的参数转换成JDBC Statement需要的参数
org.apache.ibatis.scripting.defaults.DefaultParameterHandler#setParameters
解析传入的参数

2.3 StatementHandler

负责对JDBC Statement的操作,如Statement执行查询、更新
org.apache.ibatis.executor.statement.PreparedStatementHandler#query
statementHandler1
statementHandler2

2.6 ResultSetHandler

负责将JDBC返回的ResultSet结果集转换成对象或List类型的集合
org.apache.ibatis.executor.resultset.DefaultResultSetHandler#handleRowValuesForSimpleResultMap
解析返回结果集

2.7 Executor

Mybatis执行器,负责Sql语句的执行和查询缓存的维护
org.apache.ibatis.executor.CachingExecutor#query
executor

3.Mybatis的插件使用

3.1 自定义插件完成sql语句的输出和进行排序

<!-- 需要加入mybatisConfig.xml中的配置-->
<plugins>
    <plugin interceptor="com.two.dream.interceptor.ZdyPlugin"></plugin>
</plugins>

如果是springboot项目直接: sqlSessionFactoryBean.setPlugins(new ZdyPlugin());

@Intercepts({@Signature(
        type = Executor.class, //拦截的接口
        method = "query", // 拦截的方法
        args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class} // 拦截方法的入参的参数类型
)})
public class ZdyPlugin implements Interceptor {
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        System.out.println("=========Executor===========");
        // 获取拦截方法的参数
        Object[] args = invocation.getArgs(); 
        MappedStatement mappedStatement = (MappedStatement) args[0];
        Configuration configuration = mappedStatement.getConfiguration();
        // 输出原sql语句
        SqlSource sqlSource = mappedStatement.getSqlSource();
        BoundSql boundSql = sqlSource.getBoundSql(args[1]);
        System.out.println(boundSql.getSql());
        System.out.println("==========================");
        // 修改原sql语句
        SqlSource newSqlSource = new StaticSqlSource(configuration, boundSql.getSql().concat(" order by address desc"), boundSql.getParameterMappings());
        MappedStatement newMappedStatement = this.build(mappedStatement, newSqlSource);
        // 修改原参数对象
        args[0] = newMappedStatement;
        // 输出修改后的sql
        System.out.println(newSqlSource.getBoundSql(args[1]).getSql());
        return invocation.proceed();
    }

    private MappedStatement build(MappedStatement ms, SqlSource newSqlSource){
        // 拷贝原对象的属性到新对象
        MappedStatement.Builder builder = new MappedStatement.Builder(ms.getConfiguration(), ms.getId(), newSqlSource, ms.getSqlCommandType());
        builder.resource(ms.getResource());
        builder.fetchSize(ms.getFetchSize());
        builder.statementType(ms.getStatementType());
        builder.timeout(ms.getTimeout());
        builder.parameterMap(ms.getParameterMap());
        builder.resultSetType(ms.getResultSetType());
        builder.resultMaps(ms.getResultMaps());
        builder.cache(ms.getCache());
        builder.flushCacheRequired(ms.isFlushCacheRequired());
        builder.useCache(ms.isUseCache());
        return builder.build();
    }
}

标签:分析,builder,mybatis,ibatis,apache,源码,ms,Mybatis,org
来源: https://www.cnblogs.com/fallmwu/p/13932790.html