Mybatis插件

简介:

Mybatis作为一个应用广泛的优秀的ORM开源框架,这个框架具有强大的灵活性,在四大组件(Executor,StatementHandler,ParameterHandler,ResultSetHandler)处提供了简单易用的插件扩展机制,Mybatis对持久曾的操作就是借助于四大核心对象,Mybatis支持用插件对四大核心对象进行拦截,对Mybatis来说,插件就是拦截器,用来增强核心对象的功能,增强功能本质上是借助于底层的动态代理实现的,换句话说,Mybatis中的四大对象都是代理对象;

Mybatis所允许拦截的方法如下:
  1. 执行器(Executor):update,query,commit,rollback等

  2. SQL语法构建器(StatementHandler):perpare,parameterize,batch,update,query等

  3. 参数处理器(ParameterHandler):getParameterObject,setParameters等

  4. 结果集处理器(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)