目前,向mybatis提供我们需要执行的sql
除了最常用的xml文件,和
@Select之类的注解,
还有一种@SelectProvider注解,可以利用Java类的某个方法来返回一段需要执行的sql
@SelectProvider使用示例
public interface UserMapper {
@SelectProvider(type = MySelectProvider.class, method = "findUser")
List<User> findUser(@Param("id") int id);
}
public class MySelectProvider {
public String findUser(Map<String, Object> param) {
return new SQL() {{
SELECT("*");
FROM("USER");
WHERE("id="+param.get("id"));
}}.toString();
}
}
执行UserMapper的findUser方法时,会调用MySelectProvider的findUser方法回去sql。
使用场景:
感觉不太常用,看个人喜好吧,有人喜欢java代码里写sql,会更灵活点?(xml其实也挺灵活的)
有一些mybatis的工具框架里会用到,比如通用mapper,Mapper接口集成父类接口的那些通用方法其实都是用@SelectProvider生成的,有兴趣的话可以自己去看一下。
源码分析
解析该注解的流程和解析@Select @Insert @Update @Delete 这几个注解的差不多,都是解析接口方法上面的注解,封装成MapperStatement对象,加入到Configuration的容器中。大体的流程可以看看 https://www.jianshu.com/p/94490cbd694e 这篇文章。
不同的地方在于构建SQLSource的地方。
创建ProviderSqlSource
![](https://img.haomeiwen.com/i23353704/2ede20d1f1ac28ec.png)
这方法感觉没啥看的,就是一些收集工作,并将信息设置为
ProviderSqlSource的对应属性上
![](https://img.haomeiwen.com/i23353704/09bba1e735d879df.png)
直接看创建后的ProviderSqlSource的属性值
![](https://img.haomeiwen.com/i23353704/d00498aecf8dd667.png)
这里并没有直接调用提供Java类的方法来创建SqlSource,而是重写了getBoundSql方法,类似于懒加载,等调用到mapper方法时,再调用getBoundSql()来创建具体的SqlSource。
![](https://img.haomeiwen.com/i23353704/9ff4e240ab35e0e4.png)
写个test类,调用Mapper方法测试一下。
写个测试方法,UserMapper和SelectProvider的代码就是最开始的示例代码
@SpringBootTest
@RunWith(SpringRunner.class)
public class MapperTest {
@Autowired
private UserMapper userMapper;
@org.junit.Test
public void testProvider() {
System.out.println(userMapper.findUser(2));
}
}
启动,断点打到从MappedStatement获取BoundSql对象的地方
![](https://img.haomeiwen.com/i23353704/be79126efbf166da.png)
调用ProviderSqlSource的getBoundSql()来获取BoundSql
![](https://img.haomeiwen.com/i23353704/2f329e3d83ae2c59.png)
![](https://img.haomeiwen.com/i23353704/cb717b5c8a94116c.png)
哈哈,接下来肯定是反射Provider类的对应方法,获取返回值啦
![](https://img.haomeiwen.com/i23353704/996b0152f7644a0e.png)
![](https://img.haomeiwen.com/i23353704/fe74d1e69b07f067.png)
获取到这个SQL
![](https://img.haomeiwen.com/i23353704/81c0f4d367a28a9a.png)
最后创建了个RawSqlSource,并返回BoundSql
![](https://img.haomeiwen.com/i23353704/8e2a918dacd1946d.png)
![](https://img.haomeiwen.com/i23353704/1661032b534d74ed.png)
网友评论