简介:
Mybatis作为一个应用广泛的优秀的ORM开源框架,这个框架具有强大的灵活性,在四大组件(Executor,StatementHandler,ParameterHandler,ResultSetHandler)处提供了简单易用的插件扩展机制,Mybatis对持久曾的操作就是借助于四大核心对象,Mybatis支持用插件对四大核心对象进行拦截,对Mybatis来说,插件就是拦截器,用来增强核心对象的功能,增强功能本质上是借助于底层的动态代理实现的,换句话说,Mybatis中的四大对象都是代理对象;
Mybatis所允许拦截的方法如下:
-
执行器(Executor):update,query,commit,rollback等
-
SQL语法构建器(StatementHandler):perpare,parameterize,batch,update,query等
-
参数处理器(ParameterHandler):getParameterObject,setParameters等
-
结果集处理器(ResultSetHandler):handleResultSets,handleOutputParameters等
自定义插件
@Intercepts({
@Signature(type = StatementHandler.class,
method = "prepare",
args = {Connection.class,Integer.class})
})
public class Myplugin implements Interceptor {
/**
* 拦截方法:只要被拦截的目标对象的目标方法被执行时,每次都会执行Interceptor方法
* @param invocation
* @return
* @throws Throwable
*/
@Override
public Object intercept(Invocation invocation) throws Throwable {
System.out.println("对方法进行了增强!!");
return invocation.proceed();//原方法执行
}
/**
* 把当前的拦截器生成代理对象存到拦截器链中
* @param o
* @return
*/
@Override
public Object plugin(Object o) {
Object wrap = Plugin.wrap(o, this);
return wrap;
}
/**
* 获取配置文件参数
* @param properties
*/
@Override
public void setProperties(Properties properties) {
System.out.println("获取到的配置文件的参数是:" + properties);
}
}
按照顺序在sqlMapConfig.xml配置
<plugins>
<plugin interceptor="com.yun.plugin.Myplugin">
<property name="name" value="tom"/>
</plugin>
</plugins>
@Test
public void test2() {
SqlSession sqlSession1 = sqlSessionFactory.openSession();
SqlSession sqlSession2 = sqlSessionFactory.openSession();
SqlSession sqlSession3 = sqlSessionFactory.openSession();
IUserMapper mapper1 = sqlSession1.getMapper(IUserMapper.class);
IUserMapper mapper2 = sqlSession2.getMapper(IUserMapper.class);
IUserMapper mapper3 = sqlSession3.getMapper(IUserMapper.class);
User user1 = mapper1.getUserById(1);
//清空一级缓存
sqlSession1.close();
User user = new User();
user.setId(1);
user.setUsername("Tom");
mapper3.updateUser(user);
sqlSession3.commit();
User user2 = mapper2.getUserById(1);
System.out.println(user1 == user2);
}
运行结果:
获取到的配置文件的参数是:{name=tom}
对方法进行了增强!!
对方法进行了增强!!
对方法进行了增强!!
false
结论,目标方法在执行sql语句的时候,plugin先执行,把当前的拦截器生成代理对象存到拦截器链中,意味这Myplugin生效,如果调用StatementHandler里面的prepare方法时,会进入Myplugin里面的intercept方法中来完成对该方法的增强,执行几次sql,intercept就会执行几次;
pageHelper插件
pom
<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
<plugin interceptor="com.github.pagehelper.PageHelper">
<!--name:当前数据哭的方言-->
<property name="dialect" value="mysql"/>
</plugin>
@Test
public void pageHelperTest(){
PageHelper.startPage(1,1);
List<User> users = mapper.getAllUser();
users.forEach(item -> {
System.out.println(item);
});
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());
}
运行结果:
User(id=1, username=Tom, orders=null, roles=null)
总条数:2
总页数:2
当前页:1
每页显示的条数:1
通用mapper
通用mapper就是为了解决单表CRUD,基于Mybatis的插件机制,开发人员不需要编写sql,不需要在DAO中增加方法,只要写好实体类,就能支持相应的CRUD;
pom
<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>
修改User实体
@Data
@Table(name = "user")//与数据表名对应
public class User implements Serializable {
@Id //表示主键id
@GeneratedValue(strategy = GenerationType.AUTO)//设置主键的生成策略
private Integer id;
@Column(name = "username")//与数据字段名对应
private String username;
}
mapper接口
public interface UserMapper extends Mapper<User> {
}
@Test
public void mapperTest() throws IOException {
//1.Resources工具类,配置文件的加载,把配置文件加载成字节输入流
InputStream inputStream = Resources.getResourceAsStream("sqlMapConfig.xml");
//2.解析了配置文件,并创建了sqlSessionFactory工厂
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//3.生产sqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = new User();
user.setId(2);
User user1 = mapper.selectOne(user);
System.out.println(user1);
}
运行结果
User(id=2, username=Jerry)