Mybatis接口编程示例

(1)首先定义接口编程需要的接口及其方法

public interface IUserMapper {  

	public User getById(int id);//接口方法,不需要实现
}

(2)创建mybatis的mapper文件,其中namespace的值为接口的完整类名

<mapper namespace="com.tianjunwei.learn.learn2.IUserMapper">//接口完整类名

     <select id="getById" parameterType="int"
         resultType="com.tianjunwei.learn.learn1.entity.User">
     	select * from users where id=#{id}
     </select>

 </mapper>

(3)创建接口调用操作

public class Learn2Main {

	public static void main(String [] args){

		String resource = "learn/mybatis-config.xml";
	    InputStream is = Learn1Main.class.getClassLoader().getResourceAsStream(resource);
	    SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(is);
	    SqlSession session = sessionFactory.openSession();
	    IUserMapper userMapper = session.getMapper(IUserMapper.class);//获取接口,已经是代理接口
	    userMapper.getById(1);
	    RowBounds rowBounds = new RowBounds(2, 4);//接口分页编程
	    System.out.println(userMapper.page(rowBounds).size());
	}
}

Mybatis接口编程相关的类主要有MapperProxyFactory、MapperProxy、MapperMethod和MapperRegister四个类:

MapperProxyFactory:通过类名我们可以猜到这是一个MapperProxy的工厂类,用于创建MapperProxy的,通过函数newInstance(SqlSession sqlSession)来创建MapperProxy的代理类。

源码如下:

//这个类赋值创建具体mapper接口代理对象的工厂
public class MapperProxyFactory<T> {

  //具体Mapper接口的class对象
  private final Class<T> mapperInterface;
  //该接口下面的缓存,key是方法对象,value是对接口中方法对象的封装
  private final Map<Method, MapperMethod> methodCache = new ConcurrentHashMap<Method, MapperMethod>();

  public MapperProxyFactory(Class<T> mapperInterface) {
    this.mapperInterface = mapperInterface;
  }

  public Class<T> getMapperInterface() {
    return mapperInterface;
  }

  public Map<Method, MapperMethod> getMethodCache() {
    return methodCache;
  }

  @SuppressWarnings("unchecked")
  protected T newInstance(MapperProxy<T> mapperProxy) {
	//创建一个代理类并返回
    return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
  }

  public T newInstance(SqlSession sqlSession) {
	//在这里创建MapperProxy对象,这个类实现了JDK的动态代理接口 InvocationHandler
    final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
	//调用上面的方法,返回一个接口的代理类
    return newInstance(mapperProxy);
  }

}

MapperProxy:通过类名可以猜到这个类为一个代理类,它实现了JDK动态代理接口InvocationHandler,通过查看源码发现它又不像一个真正的代理类,它一般不会真正执行被代理类的函数方法,只是在执行被代理类函数方法时来执行MapperMethod类的execute方法,具体逻辑详看invoke函数

源码如下:

//实现了JDK动态代理的接口,InvocationHandler
//在invoke方法中实现了代理方法调用的细节
public class MapperProxy<T> implements InvocationHandler, Serializable {

  private static final long serialVersionUID = -6424540398559729838L;
  //sqlSession
  private final SqlSession sqlSession;
  //接口的类型对象
  private final Class<T> mapperInterface;
  //接口中方法的缓存,由MapperProxyFactory传递过来
  private final Map<Method, MapperMethod> methodCache;

  //构造函数
  public MapperProxy(SqlSession sqlSession, Class<T> mapperInterface, Map<Method, MapperMethod> methodCache) {
    this.sqlSession = sqlSession;
    this.mapperInterface = mapperInterface;
    this.methodCache = methodCache;
  }
  //接口代理对象所有的方法调用都会调用该方法
  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
	//判断是不是基础方法比如toString、hashCode等,这些方法直接调用不需要处理
    if (Object.class.equals(method.getDeclaringClass())) {
      try {
        return method.invoke(this, args);
      } catch (Throwable t) {
        throw ExceptionUtil.unwrapThrowable(t);
      }
    }
	//进行缓存
    final MapperMethod mapperMethod = cachedMapperMethod(method);
	//调用mapperMethod.execute 核心的地方就在这个方法里,这个方法对才是真正对SqlSession进行的包装调用
    return mapperMethod.execute(sqlSession, args);
  }
  //缓存处理
  private MapperMethod cachedMapperMethod(Method method) {
    MapperMethod mapperMethod = methodCache.get(method);
    if (mapperMethod == null) {
      mapperMethod = new MapperMethod(mapperInterface, method, sqlSession.getConfiguration());
      methodCache.put(method, mapperMethod);
    }
    return mapperMethod;
  }

}

Mybatis接口编程原理分析(一)的更多相关文章

  1. Mybatis接口编程原理分析(三)

    前面两篇博客Mybatis接口编程原理分析(一)和Mybatis接口编程原理分析(二)我们介绍了MapperProxyFactory.MapperProxy和MapperMethod的操作及源码分析, ...

  2. Mybatis接口编程原理分析(二)

    在上一篇博客中 Mybatis接口编程原理分析(一)中我们介绍了MapperProxyFactory和MapperProxy,接下来我们要介绍的是MapperMethod MapperMethod:它 ...

  3. MyBatis整合Spring原理分析

    目录 MyBatis整合Spring原理分析 MapperScan的秘密 简单总结 假如不结合Spring框架,我们使用MyBatis时的一个典型使用方式如下: public class UserDa ...

  4. MyBatis的深入原理分析之1-架构设计以及实例分析

    MyBatis是目前非常流行的ORM框架,它的功能很强大,然而其实现却比较简单.优雅.本文主要讲述MyBatis的架构设计思路,并且讨论MyBatis的几个核心部件,然后结合一个select查询实例, ...

  5. MyBatis框架及原理分析

    MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架,其主要就完成2件事情: 封装JDBC操作 利用反射打通Java类与SQL语句之间的相互转换 MyBatis的主要设计目的就 ...

  6. Linux下Golang Socket编程原理分析与代码实现

    在POSIX标准推出后,socket在各大主流OS平台上都得到了很好的支持.而Golang是自带Runtime的跨平台编程语言,Go中提供给开发者的Socket API是建立在操作系统原生Socket ...

  7. Mybatis插件原理分析(三)分页插件

    在Mybatis中插件最经常使用的是作为分页插件,接下来我们通过实现Interceptor来完成一个分页插件. 虽然Mybatis也提供了分页操作,通过在sqlSession的接口函数中设置RowBo ...

  8. mybatis(一、原理,一对多,多对一查询)

    MyBatis框架及原理分析 MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架,其主要就完成2件事情: 封装JDBC操作 利用反射打通Java类与SQL语句之间的相互转换 ...

  9. Spark原理分析目录

    1 Spark原理分析 -- RDD的Partitioner原理分析 2 Spark原理分析 -- RDD的shuffle简介 3 Spark原理分析 -- RDD的shuffle框架的实现概要分析 ...

随机推荐

  1. Jenkins 2.x版本修改启动端口号

    直接修改jenkins.xml中arguments的httpPort 然后,重启jenkins.

  2. 使用linux部署tomcat项目

    1.下载对应的Tomcat服务器包 Apache Tomcat官网下载: http://tomcat.apache.org/download-70.cgi 比如我们使用的是  apache-tomca ...

  3. JAVA 练习 找出素数

    package com.zhang.hello; public class Task { /** * 1. 输出打印九九乘法表 * */ public void NO1(){ for(int i=1; ...

  4. ubuntu 英文系统下安装中文输入法

    环境:ubuntu15.10 64位 英文版 软件:fcitx输入法框架,及多种拼音输入法 linux的英文系统会比中文少很多麻烦,特别是在命令行输入路径的时候,如果路径是中文将是一件很头疼的问题.但 ...

  5. 06 Nexus仓储/基础设施 - DevOps之路

    06 Nexus仓储/基础设施 - DevOps之路 文章Github地址,欢迎start:https://github.com/li-keli/DevOps-WiKi Nexus仓储官网简介: Th ...

  6. beta 分布的详细介绍(转载)

    目前看到的关于beta分布最好的一个解释,由于贴过来格式不好看,所以附上链接: http://www.datalearner.com/blog/1051505532393058

  7. JavaScript If…Else 语句

    条件语句用于基于不同的条件来执行不同的动作. 条件语句 通常在写代码时,您总是需要为不同的决定来执行不同的动作.您可以在代码中使用条件语句来完成该任务. 在 JavaScript 中,我们可使用以下条 ...

  8. MySQL命令行SQL脚本的导入导出小结(数据库的备份与还原)

    1.设置环境变量 要想在命令行下各处都能执行mysql命令,必须在系统变量Path中添加mysql的命令所在的目录.例如我安装的是集成PHP环境的mysql,在D盘xampps下,则我需要将" ...

  9. Scala:数组

    http://blog.csdn.net/pipisorry/article/details/52902432 ) 或var z = new Array[String](3) 以上语法中,z 声明一个 ...

  10. VMware 下的CentOS6.7 虚拟机与Windows7通信

    在有网络的情况下,VMware 虚拟机使用桥接模式(Bridged) 和NAT方式,会自动通信,但是在没有网络的情况下怎么办呢?对,是的,使用host-only模式,如何设置呢? 注:将Windows ...