spring启动时mybatis-plus注入sql源码解析

MP在spring启动就会挨个分析xxxMapper中的方法,并且将对应的SQL语句处理好,保存到configuration对象中的mappedStatements中。

 

首先,在contextApplication.xml文件中配置的sqlSessionFactory配置的是mybatisplus的MyBatisSqlSessionFactoryBean,其implements

ApplicationListener,

FactoryBean<SqlSessionFactory>,

InitializingBean

ssm启动信息

前置知识:

Spring的InitializingBean接口有很好的用处,位于spring beans中,它只提供一个方法afterPropertiesSet(),当你实现了该方法后,spring就会对你提供框架级的支持:当你通过sring容器生产出实现了该接口的类的实例后,它就会调用afterPropertiesSet方法,通过这个方法,你可以检查你的bean是否正确地被初始化了。

在com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean#afterPropertiesSet中

 

this.sqlSessionFactory = buildSqlSessionFactory();

 

在buildSqlSessionFactory方法中

final MybatisConfiguration targetConfiguration;
SqlSessionFactory sqlSessionFactory = this.sqlSessionFactoryBuilder.build(targetConfiguration);

初始化我们后面要使用的MybatisConfiguration

通过调用栈,可以看到,后面其执行了DaoSupport中的方法,DaoSupport也实现了InitializingBean,其afterPropertiesSet()方法中

checkDaoConfig();

最后执行的是MapperFactoryBean中的checkDaoConfig方法

Configuration configuration = getSqlSession().getConfiguration();
configuration.addMapper(this.mapperInterface);

 

在MyBatisConfiguration中

/**

 * 使用自己的 MybatisMapperRegistry

 */

@Override

public <T> void addMapper(Class<T> type) {

    mybatisMapperRegistry.addMapper(type);

}

 

其addMapper方法进入到mybatis-plus中 MyBatisMapperRegistry

之后执行

 

MybatisMapperAnnotationBuilder parser = new MybatisMapperAnnotationBuilder(config, type);
parser.parse();

 

进入到MybatisMapperAnnotationBuilder中(这个是mybatis中的对象)

注意:在其构造函数中,构造了后面要使用的MapperBuilderAsssistant

this.assistant = new MapperBuilderAssistant(configuration, resource);

 

执行parse方法

GlobalConfigUtils.getSqlInjector(configuration).inspectInject(assistant, type);

返回DefaultSqlInjector,执行inspectInject方法

在AbstractSqlInjector中,得到methodList,逐个执行inject方法

List<AbstractMethod> methodList = this.getMethodList();
// 循环注入自定义方法

methodList.forEach(m -> m.inject(builderAssistant, mapperClass, modelClass, tableInfo));

之后在AbstractMethod中执行inject方法,调用其抽象方法injectMappedStatement

/**

 * 注入自定义方法

 */

public void inject(MapperBuilderAssistant builderAssistant, Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {

    /* 注入自定义方法 */

    injectMappedStatement(mapperClass, modelClass, tableInfo);

}

AbstractMethod的继承关系

抽象方法在子类中有不同的实现类

如方法是selectById,那么就会进入到SelectById子类中,调用其injectMappedStatement,准备好参数后,再调用AbstractMethod中的addMappedStatement方法

public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {

    SqlMethod sqlMethod = SqlMethod.LOGIC_SELECT_BY_ID;

    SqlSource sqlSource = new RawSqlSource(configuration, String.format(sqlMethod.getSql(),

        sqlSelectColumns(tableInfo, false),

        tableInfo.getTableName(), tableInfo.getKeyColumn(), tableInfo.getKeyProperty(),

        tableInfo.getLogicDeleteSql(true, false)), Object.class);

    return this.addSelectMappedStatement(mapperClass, sqlMethod.getMethod(), sqlSource, modelClass, tableInfo);

}

SqlMethod : 枚举对象,MP支持的SQL方法

LOGIC_SELECT_BY_ID("selectById", "根据ID 查询一条数据", "SELECT %s FROM %s WHERE %s=#{%s} %s"),

 

TableInfo:数据库表反射信息,可以获取到数据库表相关的信息

 

其通过String.format来构造sql,包括sql语句及对应的表,列名,参数,主键列等,对应到%s上

String.format(sqlMethod.getSql(),

    sqlSelectColumns(tableInfo, false),

    tableInfo.getTableName(), tableInfo.getKeyColumn(), tableInfo.getKeyProperty(),

    tableInfo.getLogicDeleteSql(true, false))

 

public RawSqlSource(Configuration configuration, String sql, Class<?> parameterType) {

最后得到的sql:

<script>

INSERT INTO tbl_employee <trim prefix="(" suffix=")" suffixOverrides=",">

<if test="lastName != null">last_name,</if>

<if test="email != null">email,</if>

<if test="gender != null">gender,</if>

<if test="age != null">age,</if>

</trim> VALUES <trim prefix="(" suffix=")" suffixOverrides=",">

<if test="lastName != null">#{lastName},</if>

<if test="email != null">#{email},</if>

<if test="gender != null">#{gender},</if>

<if test="age != null">#{age},</if>

</trim>

</script>

 

构造出一个SqlSource

SqlSource: SQL语句处理对象

 

MapperBuilderAssistant:用于缓存、SQL参数、查询方法结果集处理等

通过MapperBuilderAssistant将每一个mappedStatement 添加到configuration中的mappedstatements中

MappedStatement statement = statementBuilder.build();

configuration.addMappedStatement(statement);

 

这个configuration为mybatis-plus的MyBatisConfiguration,调用其addMappedStatement方法

public void addMappedStatement(MappedStatement ms) {

    logger.debug("addMappedStatement: " + ms.getId());

    super.addMappedStatement(ms);

}

在这里打印日志

之后调用mybatis Configuration中的addMappedStatement方法,真正将方法添加到mappedStatements中

public void addMappedStatement(MappedStatement ms) {

  mappedStatements.put(ms.getId(), ms);

}

 

这样就在Configuration的mappedStatements中注入了这17个BaseMapper提供的方法

这个过程的流程图:

项目源码参考:https://gitee.com/constfafa/mybatis-plus-spring-demo.git

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot和MyBatis-Plus是两个流行的Java开发框架。Spring Boot是一个用于简化和加速Java应用程序开发的框架,而MyBatis-Plus是MyBatis的增强版,提供了更多的特性和功能。 使用Spring Boot2和MyBatis-Plus的组合,能够使开发过程更加高效和简便。Spring Boot2已经集成了很多常用的配置和功能,例如自动配置、快速启动器和监控等。这些功能使得开发者可以更加专注于业务逻辑而不用过多关注繁琐的配置。 而MyBatis-Plus提供了一系列强大且易于使用的功能,例如代码生成器、分页查询、逻辑删除和性能优化等。代码生成器能够帮助开发者快速生成数据库表对应的实体类、Mapper接口以及XML映射文件,大大提高了开发效率。分页查询和逻辑删除功能使得数据操作更加方便和灵活。另外,MyBatis-PlusSQL语句进行了优化,能够提升数据库查询的性能。 使用Spring Boot2和MyBatis-Plus的组合还能够更好地兼容其他常用的开发工具和框架,例如Spring Security和Swagger等。Spring Security提供了安全认证和授权的功能,能够保护应用程序的安全性。Swagger可以生成API文档,并提供了一个用户友好的UI界面,方便开发者进行接口测试和调试。 总之,Spring Boot2和MyBatis-Plus的组合能够提高开发效率、简化配置、优化性能并提供额外的功能。对于Java开发者来说,这是一个非常不错且受欢迎的选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值