咱们在应用 mybatis 的时候,少数状况下都是创立一个对应 mapper 的 xml 文件来写 sql 语句,这种形式也是官网举荐并且是最灵便的形式。但其实 mybatis 也反对通过注解的形式来实现 sql 语句。本篇文章就是聊聊 mybatis 是如何应用注解形式来实现 sql 执行的。
知识点
- 什么是注解
- 如何应用
- 实现原理
什么是注解
翻译过去可能很多人不分明,翻译回去就是 Annotation。咱们平时在代码中肯定用到很多注解,特地是 springboot 我的项目,看上面的例子你就明确了
@SpringBootApplication
public class MybatisAnalyzeApplication {public static void main(String[] args) {SpringApplication.run(MybatisAnalyzeApplication.class, args);
}
}
这是非常简单的一个 springboot 启动类,这个 @SpringBootApplication
就是注解。
如何应用
mybatis 注解形式的应用非常简单,间接在你定义的 Mapper 接口对应的办法上加一个注解就能够了,间接上代码:
@Repository
public interface UserInfoMapper {UserInfo selectById(int id);
@Select("select * from user_info where user_name = #{userName}")
List<UserInfo> select(String userName, String nickName);
int insert(UserInfo userInfo);
int update(int id, String nickName);
}
能够看到 UserInfoMapper
接口中的 select
办法下面有一个 @Select
的注解,这样就完了。其余几个没有加注解的办法,还是须要定义 xml 文件(注解形式和 xml 形式是能够混用的),须要留神的是 xml 文件中不能再定义曾经加过注解的办法,否走会抛出异样。同样的,对于增、改、删操作,加上注解 @Insert
、@Update
、@Delete
即可。
如果咱们还须要用到一些启用缓存、期待超时工夫等属性怎么办呢,这些可是在原来的 xml 配置中能够配置的。别急,能够再加一个 @Options
注解,如下
@Options(useCache = true, timeout = 3000)
@Select("select * from user_info where user_name = #{userName}")
List<UserInfo> select(String userName, String nickName);
当然还有 @SelectKey
、@ResultMap
等注解是和原来的 xml 形式配置对应起来的,不过这里是有局限性的,比方 @ResultMap
就须要联合 xml 配置来应用,这也是为什么官网举荐 xml 形式的起因之一。
实现原理
最初咱们来理解一下 mybatis 是如何实现注解形式来执行 sql 的,顺带的介绍一下为什么咱们定义的 mapper 明明是接口类型,为什么可能在代码中间接应用。先来看一下注解所在包
下面这个包里蕴含了所有注解类型,基本上和 xml 配置的属性是能够关联起来的,如果不晓得 xml 形式对应的注解形式怎么应用,能够间接到这里看看。接着看下哪里启动时加载 mapper 的中央 `org.apache.ibatis.binding.MapperRegistry#addMapper
在这个逻辑中,咱们能够看到有一个 knownMappers
,它是寄存所有咱们定义的 mapper 接口的,对应的 value 类型是MapperProxyFactory
,这个类型很重要,前面再讲。能够看到这个类型MapperAnnotationBuilder
,看名称就晓得是专门对注解形式进行解决的类,与之对应的解决 xml 的类就是XMLMapperBuilder
。跟进去看下parser.parse()
逻辑
这里优先会去解析 xml 配置,接着一一解析 mapper 的办法,跟进去看下如何解析的
能够看到这里就对注解进行解析了,办法上的注解肯定要在以下范畴内能力解析
前面每个注解的解析就不介绍了,比较简单。
集成 spring
为什么咱们定义的 mapper 明明是接口类型,为什么可能在代码中间接应用?这是因为集成了 spring,由 mybatis-spring 包帮咱们做掉了。咱们平时在 spring 中应用的还是须要指定扫描的 mapper 包所在门路,注解形式就是@MapperScan
它会通过 MapperScannerRegistrar
将 mapper 注册为 bean,最终在 org.mybatis.spring.mapper.ClassPathMapperScanner#processBeanDefinitions
设置理论的 mapper 类型(MapperFactoryBean)
而 MapperFactoryBean
是一个 FactoryBean
,所以理论的 bean 是通过它的getObject
办法获取到的
跟进去最终在这里获取 `org.apache.ibatis.binding.MapperRegistry#getMapper
其实就是一个动静代理。
总结
注解这一块实现还是比较简单的,对于集成 spring 并做动静代理的形式,咱们本人的代码里也能够参考。
参考资料
https://mybatis.org/mybatis-3…