31、Mybatis进阶:插件原理及使用

目录

1说明

1、 1;

2自定义一个插件

2、 1创建一个java文件;

2、 2说明下这个自定义的插件类;

2、 2.1自定义插件类,必须实现Interceptor接口;

2、 2.2;

2、 2.3;

2、 2.4;

2、 2.5;

2、 2注册这个自定义的插件类;

2、 3测试;

2、 4效果;

3自定义多个插件时,该如何执行呢

3、 1定义第二个插件类;

3、 2注册两个插件类方式;

3、 3执行效果;

4使用一个强大的分页插件

4、 1下载插件;

4、 1.1百度搜索PageHelper;

4、 1.2可以选择中文文档;

4、 1.3下jar包;

4、 2引入jar包;

4、 3只是在Junit中使用方式变了而已,其他地方都不变;

4、 4mybatis中还需要引入该插件;

4、 5效果;


1说明

1.1

本文内容整合 http://www.gulixueyuan.com/my/course/43任务79至任务83的内容

1、 2;

本文代码基于HellWorld代码

2自定义一个插件

2.1创建一个java文件

package com.atguigu.mybatis.dao;

import java.util.Properties;

import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;

/**
 * 完成插件签名:
 *		告诉MyBatis当前插件用来拦截哪个对象的哪个方法
 */
@Intercepts(
		{
			@Signature(type=StatementHandler.class,method="parameterize",args=java.sql.Statement.class)
		})
public class MyFirstPlugin implements Interceptor{

	/**
	 * intercept:拦截:
	 * 		拦截目标对象的目标方法的执行;
	 */
	@Override
	public Object intercept(Invocation invocation) throws Throwable {
		// TODO Auto-generated method stub
		System.out.println("MyFirstPlugin...intercept:"+invocation.getMethod());
		//动态的改变一下sql运行的参数:以前1号员工,实际从数据库查询3号员工
		Object target = invocation.getTarget();
		System.out.println("当前拦截到的对象:"+target);
		//拿到:StatementHandler==>ParameterHandler===>parameterObject
		//拿到target的元数据
		MetaObject metaObject = SystemMetaObject.forObject(target);
		Object value = metaObject.getValue("parameterHandler.parameterObject");
		System.out.println("sql语句用的参数是:"+value);
		//修改完sql语句要用的参数
		metaObject.setValue("parameterHandler.parameterObject", 11);
		//执行目标方法
		Object proceed = invocation.proceed();
		//返回执行后的返回值
		return proceed;
	}

	/**
	 * plugin:
	 * 		包装目标对象的:包装:为目标对象创建一个代理对象
	 */
	@Override
	public Object plugin(Object target) {
		// TODO Auto-generated method stub
		//我们可以借助Plugin的wrap方法来使用当前Interceptor包装我们目标对象
		System.out.println("MyFirstPlugin...plugin:mybatis将要包装的对象"+target);
		Object wrap = Plugin.wrap(target, this);
		//返回为当前target创建的动态代理
		return wrap;
	}

	/**
	 * setProperties:
	 * 		将插件注册时 的property属性设置进来
	 */
	@Override
	public void setProperties(Properties properties) {
		// TODO Auto-generated method stub
		System.out.println("插件配置的信息:"+properties);
	}

}

2.2说明下这个自定义的插件类

2.2.1自定义插件类,必须实现Interceptor接口

2.2.2

plugin方法,会比intercept方法先执行。因为plugin方法是得到一个动态代理对象,在执行这个动态代理对象指定的方法时才会执行intercept方法

2.2.3

必须有Intercepts注解

type:指定要拦截的哪个对象(mybatis四大对象都可以被拦截到)

method:指定要拦截到对象的方法名

args:指定了对象的方法名还不够,还需要精确到入参。(防止类加载的情况发生

2.2.4

这个拦截器的功能是:

改变一下sql运行的参数:无论想查询处几号员工,实际从数据库都查询的是11号员工。

@Override
	public Object intercept(Invocation invocation) throws Throwable {
		// TODO Auto-generated method stub
		System.out.println("MyFirstPlugin...intercept:"+invocation.getMethod());
		//动态的改变一下sql运行的参数:以前1号员工,实际从数据库查询3号员工
		Object target = invocation.getTarget();
		System.out.println("当前拦截到的对象:"+target);
		//拿到:StatementHandler==>ParameterHandler===>parameterObject
		//拿到target的元数据
		MetaObject metaObject = SystemMetaObject.forObject(target);
		Object value = metaObject.getValue("parameterHandler.parameterObject");
		System.out.println("sql语句用的参数是:"+value);
		//修改完sql语句要用的参数
		metaObject.setValue("parameterHandler.parameterObject", 11);
		//执行目标方法
		Object proceed = invocation.proceed();
		//返回执行后的返回值
		return proceed;
	}

2.2.5

剩下的说明,可以看下该插件类中的注释

2.2注册这个自定义的插件类

下面的plugins就是注释插件的。property就是设置属性值的

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
 PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
 "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

	<!--plugins:注册插件  -->
	<plugins>
		<plugin interceptor="com.atguigu.mybatis.dao.MyFirstPlugin">
			<property name="username" value="root"/>
			<property name="password" value="123456"/>
		</plugin>
	</plugins>
	<environments default="development">
		<environment id="development">
			<transactionManager type="JDBC" />
			<dataSource type="POOLED">
				<property name="driver" value="com.mysql.jdbc.Driver" />
				<property name="url" value="jdbc:mysql://localhost:3306/mybatis" />
				<property name="username" value="root" />
				<property name="password" value="123456" />
			</dataSource>
		</environment>
	</environments>
	<!-- 将我们写好的sql映射文件(EmployeeMapper.xml)一定要注册到全局配置文件(mybatis-config.xml)中 -->
	<mappers>
		<mapper resource="EmployeeMapper.xml" />
	</mappers>
</configuration>

2.3测试

	@Test
	public void test01() throws IOException {
		// 1、获取sqlSessionFactory对象
		SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
		// 2、获取sqlSession对象
		SqlSession openSession = sqlSessionFactory.openSession();
		try {
			// 3、获取接口的实现类对象
			//会为接口自动的创建一个代理对象,代理对象去执行增删改查方法
			EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
			Employee employee = mapper.getEmpById(1);
			System.out.println(mapper);
			System.out.println(employee);
		} finally {
			openSession.close();
		}

	}

2.4效果

*

3自定义多个插件时,该如何执行呢

3.1定义第二个插件类

package com.atguigu.mybatis.dao;

import java.util.Properties;

import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;

@Intercepts(
		{
			@Signature(type=StatementHandler.class,method="parameterize",args=java.sql.Statement.class)
		})
public class MySecondPlugin implements Interceptor{

	@Override
	public Object intercept(Invocation invocation) throws Throwable {
		System.out.println("MySecondPlugin...intercept:"+invocation.getMethod());
		return invocation.proceed();
	}

	@Override
	public Object plugin(Object target) {
		// TODO Auto-generated method stub
		System.out.println("MySecondPlugin...plugin:"+target);
		return Plugin.wrap(target, this);
	}

	@Override
	public void setProperties(Properties properties) {
		// TODO Auto-generated method stub
	}

}

3.2注册两个插件类方式

<!--plugins:注册插件  -->
	<plugins>
		<plugin interceptor="com.atguigu.mybatis.dao.MyFirstPlugin">
			<property name="username" value="root"/>
			<property name="password" value="123456"/>
		</plugin>
		<plugin interceptor="com.atguigu.mybatis.dao.MySecondPlugin"></plugin>
	</plugins>

说明:如果两个自定义的插件类都同时拦截同一个对象的里的同一方法。这里的编写顺序就决定了先创建代理对象的先后顺序。这里表示先创建com.atguigu.mybatis.dao.MyFirstPlugin的代理对象,根据源码可知会把这个代理对象在创建一次变成com.atguigu.mybatis.dao.MySecondPlugin的代理对象。

即就是:创建动态代理的时候,是按照插件配置顺序创建层层代理对象。 执行目标方法的之后,按照逆向顺序执行

3.3执行效果

*

4使用一个强大的分页插件

说明代码还是基于HellWorld代码

4.1下载插件

这个插件是mybatis的非常强大的分页插件

4.1.1百度搜索PageHelper

*

4.1.2可以选择中文文档

*

4.1.3下jar包

*

4.2引入jar包

*

4.3只是在Junit中使用方式变了而已,其他地方都不变

改代码中的info与page对象都可以打印出分页的详细信息。具体操作可参考

http://www.gulixueyuan.com/course/43/task/1232/show的任务83:MyBatis_扩展_分页_PageHelpler分页插件使用

@Test
	public void test01() throws IOException {
		// 1、获取sqlSessionFactory对象
		SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
		// 2、获取sqlSession对象
		SqlSession openSession = sqlSessionFactory.openSession();
		try {
			EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
			Page<Object> page = PageHelper.startPage(5, 1);
			
			List<Employee> emps = mapper.getEmps();
			//传入要连续显示多少页
			PageInfo<Employee> info = new PageInfo(emps, 5);
			for (Employee employee : emps) {
				System.out.println(employee);
			}
			System.out.println("当前页码:"+page.getPageNum());
			System.out.println("总记录数:"+page.getTotal());
			System.out.println("每页的记录数:"+page.getPageSize());
			System.out.println("总页码:"+page.getPages());

			///xxx
			System.out.println("当前页码:"+info.getPageNum());
			System.out.println("总记录数:"+info.getTotal());
			System.out.println("每页的记录数:"+info.getPageSize());
			System.out.println("总页码:"+info.getPages());
			System.out.println("是否第一页:"+info.isIsFirstPage());
			System.out.println("连续显示的页码:");
			int[] nums = info.getNavigatepageNums();
			for (int i = 0; i < nums.length; i++) {
				System.out.println(nums[i]);
			}
			
			
			//xxxx
		} finally {
			openSession.close();
		}

	}

4.4mybatis中还需要引入该插件

	<plugins>
		<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
	</plugins>

4.5效果

*

版权声明:本文不是「本站」原创文章,版权归原作者所有 | 原文地址: