mybatis运行原理

总体流程概述 

 

* 1、获取sqlSessionFactory对象:
*     解析文件的每一个信息保存在Configuration中,返回包含Configuration的DefaultSqlSession;
*     注意:【MappedStatement】:代表一个增删改查的详细信息

* 2、获取sqlSession对象
*     返回一个DefaultSQlSession对象,包含Executor和Configuration;
*     这一步会创建Executor对象;
* 3、获取接口的代理对象(MapperProxy)
*     getMapper,使用MapperProxyFactory创建一个MapperProxy的代理对象
*     代理对象里面包含了,DefaultSqlSession(Executor)


* 4、执行增删改查方法
 总结:
*  1、根据配置文件(全局,sql映射)初始化出Configuration对象
*  2、创建一个DefaultSqlSession对象,
*     他里面包含Configuration以及
*     Executor(根据全局配置文件中的defaultExecutorType创建出对应的Executor)
*  3、DefaultSqlSession.getMapper():拿到Mapper接口对应的MapperProxy;
*  4、MapperProxy里面有(DefaultSqlSession);
*  5、执行增删改查方法:
*         1)、调用DefaultSqlSession的增删改查(Executor);
*         2)、会创建一个StatementHandler对象。
*            (同时也会创建出ParameterHandler和ResultSetHandler)
*         3)、调用StatementHandler预编译参数以及设置参数值;
*            使用ParameterHandler来给sql设置参数
*         4)、调用StatementHandler的增删改查方法;
*         5)、ResultSetHandler封装结果
*  注意:
*      四大对象每个创建的时候都有一个interceptorChain.pluginAll(parameterHandler);

代码实现

 通用mapper就是预先将一些方法映射成  MappedStatement存起来,mybatis-plus就集成了通用mapper

插件机制

生成   Executor,StatementHandler ,ParameterHandler,ResultSetHandler 这几大对象时,都会对其进行包装生成代理对象。代理对象可拦截要执行的方法。

 

 

package org.apache.ibatis.plugin;

public interface Interceptor {
   
  //拦截指定的方法
  Object intercept(Invocation invocation) throws Throwable;

 //生成代理对象
  Object plugin(Object target);

//设置属性相关值
  void setProperties(Properties properties);

}
/**
 * 完成插件签名:
 *		告诉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);
	}

}

/*
PageHelper 的拦截分页方法 举例

*/
@Intercepts(
        {
                @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
                @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}),
        }
)
public class PageInterceptor implements Interceptor {

}

二级缓存(和插件机制无关)

一级缓存时会话级别

二级缓存是命名空间级别(二级缓存可以指定缓存实现默认map实现 可以用ecache等)

详细介绍:

http://t.csdn.cn/s4Xl6 

代码测试 

<?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>
	<settings>
		<!-- 打印查询语句 -->
		<setting name="logImpl" value="STDOUT_LOGGING" />
	</settings>

	<plugins>

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

	</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="" />
			</dataSource>
		</environment>
	</environments>
	<!-- 将我们写好的sql映射文件(EmployeeMapper.xml)一定要注册到全局配置文件(mybatis-config.xml)中 -->
	<mappers>
		<mapper resource="EmployeeMapper.xml" />
	</mappers>
</configuration>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
 PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="mybatis.dao.EmployeeMapper">
<!-- 
namespace:名称空间;指定为接口的全类名
id:唯一标识
resultType:返回值类型
#{id}:从传递过来的参数中取出id值

public Employee getEmpById(Integer id);
 -->
	<select id="getEmpById" resultType="mybatis.bean.Employee"
		>
		select id,last_name lastName,email,gender from tbl_employee where id = #{id}
	</select>

	<select id="getEmpByName" resultType="mybatis.bean.Employee">
		select id,last_name lastName,email,gender from tbl_employee where last_name = #{name}
	</select>
</mapper>

public class MyBatisTest {

	public SqlSessionFactory getSqlSessionFactory() throws IOException {
		String resource = "mybatis-config.xml";
		InputStream inputStream = Resources.getResourceAsStream(resource);
		return new SqlSessionFactoryBuilder().build(inputStream);
	}

	/**
	 * 1、获取sqlSessionFactory对象:
	 * 		解析文件的每一个信息保存在Configuration中,返回包含Configuration的DefaultSqlSession;
	 * 		注意:【MappedStatement】:代表一个增删改查的详细信息
	 * 
	 * 2、获取sqlSession对象
	 * 		返回一个DefaultSQlSession对象,包含Executor和Configuration;
	 * 		这一步会创建Executor对象;
	 * 
	 * 3、获取接口的代理对象(MapperProxy)
	 * 		getMapper,使用MapperProxyFactory创建一个MapperProxy的代理对象
	 * 		代理对象里面包含了,DefaultSqlSession(Executor)
	 * 4、执行增删改查方法
	 * 
	 * 总结:
	 * 	1、根据配置文件(全局,sql映射)初始化出Configuration对象
	 * 	2、创建一个DefaultSqlSession对象,
	 * 		他里面包含Configuration以及
	 * 		Executor(根据全局配置文件中的defaultExecutorType创建出对应的Executor)
	 *  3、DefaultSqlSession.getMapper():拿到Mapper接口对应的MapperProxy;
	 *  4、MapperProxy里面有(DefaultSqlSession);
	 *  5、执行增删改查方法:
	 *  		1)、调用DefaultSqlSession的增删改查(Executor);
	 *  		2)、会创建一个StatementHandler对象。
	 *  			(同时也会创建出ParameterHandler和ResultSetHandler)
	 *  		3)、调用StatementHandler预编译参数以及设置参数值;
	 *  			使用ParameterHandler来给sql设置参数
	 *  		4)、调用StatementHandler的增删改查方法;
	 *  		5)、ResultSetHandler封装结果
	 *  注意:
	 *  	四大对象每个创建的时候都有一个interceptorChain.pluginAll(parameterHandler);
	 * 
	 * @throws IOException
	 */
	@Test
	public void test01() throws IOException {
		// 1、获取sqlSessionFactory对象
		SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
		// 2、获取sqlSession对象
		SqlSession openSession = sqlSessionFactory.openSession();
		try {
			// 3、获取接口的实现类对象
			//会为接口自动的创建一个代理对象,代理对象去执行增删改查方法
			PageHelper.startPage(1,5);
			EmployeeMapper mapper = openSession.getMapper(EmployeeMapper.class);
			Employee employee = mapper.getEmpByName("zhangsan");
			System.out.println(mapper);
			System.out.println(employee);
		} finally {
			openSession.close();
		}

	}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值