mybatis插件
1.插件介绍
Mybati s作为一个应用广泛的优秀的ORM开源框架,这个框架具有强大的灵活性,在四大组件
(Executor、StatementHandler、ParameterHandler、ResultSetHandler)处提供了简单易用的插 件扩
展机制。Mybatis对持久层的操作就是借助于四大核心对象。MyBatis支持用插件对四大核心对象进 行
拦截,对mybatis来说插件就是拦截器,用来增强核心对象的功能,增强功能本质上是借助于底层的 动
态代理实现的,换句话说,MyBatis中的四大对象都是代理对象
MyBatis所允许拦截的方法如下:
- 执行器Executor (update、query、commit、rollback等方法);
- SQL语法构建器StatementHandler (prepare、parameterize、batch、updates query等方法);
- 参数处理器ParameterHandler (getParameterObject、setParameters方法);
- 结果集处理器ResultSetHandler (handleResultSets、handleOutputParameters等方法);
2.插件原理
插件具体是如何拦截并附加额外的功能的呢?以ParameterHandler来说
public ParameterHandler newParameterHandler(MappedStatement mappedStatement,Object object, BoundSql sql, InterceptorChain interceptorChain){
ParameterHandler parameterHandler = mappedStatement.getLang().createParameterHandler(mappedStatement,object,sql);
parameterHandler = (ParameterHandler) interceptorChain.pluginAll(parameterHandler);
return parameterHandler;
}
public Object pluginAll(Object target) {
for (Interceptor interceptor : interceptors) {
target = interceptor.plugin(target);
}
return target;
}
interceptorChain保存了所有的拦截器(interceptors),是mybatis初始化的时候创建的。调用拦截器链 中的拦截器依次的对目标进行拦截或增强。interceptor.plugin(target)中的target就可以理解为mybatis 中的四大对象。返回的target是被重重代理后的对象
3.使用示例
如果我们想要拦截Executor的query方法,那么可以这样定义插件:
@Intercepts({
@Signature(
type = Executor.class,
method = "query",
args= {MappedStatement.class,Object.class,RowBounds.class,ResultHandler.class}
)
})
public class ExeunplePlugin implements Interceptor {
//省略逻辑
}
除此之外,我们还需将插件配置到sqlMapConfig.xm l中
<plugins>
<plugin interceptor="com.example.demo.plugin.ExamplePlugin"></plugin>
</plugins>
Mybatis 插件接口-Interceptor
- Intercept方法,插件的核心方法
- plugin方法,生成target的代理对象
- setProperties方法,传递插件所需参数
4.分页插件
- maven依赖
<!-- 分页助手 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>3.7.5</version>
</dependency>
<dependency>
<groupId>com.github.jsqlparser</groupId>
<artifactId>jsqlparser</artifactId>
<version>0.9.1</version>
</dependency>
- sqlMapConfig.xml配置
<!--注意:分页助手的插件 配置在通用馆mapper之前-->
<plugin interceptor="com.github.pagehelper.PageHelper">
<!-- 指定方言 -->
<property name="dialect" value="mysql"/>
</plugin>
- 代码示例
/**
* 测试分页
*/
@Test
public void test2() {
UserMapper mapper = session.getMapper(UserMapper.class);
PageHelper.startPage(1, 2);
List<User> users = mapper.findAll();
for (User user : users) {
System.out.println(user);
}
PageInfo<User> pageInfo = new PageInfo<>(users);
System.out.println("总条数:" + pageInfo.getTotal());
System.out.println("总页数:" + pageInfo.getPages());
System.out.println("当前页:" + pageInfo.getPageNum());
System.out.println("每页显示的条数:" + pageInfo.getPageSize());
}
5.通用Mapper
- 引入依赖
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper</artifactId>
<version>3.1.2</version>
</dependency>
- sqlMapConfig.xml配置
<plugin interceptor="tk.mybatis.mapper.mapperhelper.MapperInterceptor">
<!--指定当前通用mapper接口使用的是哪一个-->
<property name="mappers" value="tk.mybatis.mapper.common.Mapper"/>
</plugin>
- 代码示例
由于extends Mapper
,有很多通用方法可直接调用,但一般我们现在不用这,mybatis-plus会更好用些
/**
* 测试通用mapper
* extends Mapper<T>
*/
@Test
public void test3() {
UserMapperPluginMapper mapper = session.getMapper(UserMapperPluginMapper.class);
User user = new User();
user.setId(8);
User user1 = mapper.selectOne(user);
System.out.println(user1);
}