Mapper接口


title:Mapper接口
date:2017年11月25日17:27:07
categories: Mybatis


前言

之前在说到Mybatis插件的时候说以后要好好分析下Mybatis的四大组件,之前一直在为公司忙搭建RocketMQ消息集群的事情,就耽误了一段时间,最近终于有时间来分析下了,要分析四大组件,还是要从一次完整的查询过程说起,把Mybatis的核心源码都过一遍。

从一次查询说起

我们做一次Mybatis的查询测试

    @Test
    public void testSelect() {
        SqlSession session = null;
        try {
            session = MybatisUtil.getCurrentSession();
            UserDao userDao = session.getMapper(UserDao.class);
            List<Integer> list = new ArrayList<Integer>();
            list.add(1);
            list.add(3);
            list.add(25);
            List<User> userList = userDao.queryList(list);
            System.out.println(JSON.toJSONString(userList));

        } catch (Exception e) {
            // TODO: handle exception
        } finally {
            if (session != null)
                session.close();
        }
    }

对应的Mapper配置文件

<?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="com.wangcc.mybatis.dao.UserDao">
<resultMap type="User" id="UserMapper">
<result property="id" column="t_id"/>
<result property="name" column="t_name"/>
</resultMap>
<select id="queryList" resultMap="UserMapper">
select * from t_user where t_id in 
<foreach collection="list" item="uId" index="index" open="(" separator="," close=")">#{uId}</foreach>

</select>
<insert id="insert" parameterType="User">

insert into t_user (t_name,address) values(#{name},#{address})
</insert>
<insert id="batchInsert" >
insert into t_user (t_name,address) values <foreach collection="list" item="user" separator=",">
(#{user.name},#{user.address})
</foreach>

</insert>
</mapper>

如果你是初次使用Mybatis,那么你一定会好奇为什么这里的UserDao都是接口并不是具体的实现类。

而如果你熟悉JDK动态代理,那么一看到这种接口可以直接执行方法的情况,那么肯定是用了代理,那么虽然我们能够知道为什么可以直接执行,但是我们也要了解他具体是怎么实现的。我们就以

            UserDao userDao = session.getMapper(UserDao.class);

为Debug入口。

进入getMapper方法

  public <T> T getMapper(Class<T> type) {
    return configuration.<T>getMapper(type, this);
  }

我们发现还是调用了构建SqlSession的最重要的对象Configuration的方法。

DefaultSqlSession对象中保存着Configuration对象的引用。

进入到Configuration中

  public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
    return mapperRegistry.getMapper(type, sqlSession);
  }

我们发现是调用的MapperRegistry对象(Configuration保存着其引用,在初始化Mybatis的配置文件的时候,就会将所有的Mapper接口注册到MapperRegistry的Map\

public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
  //在knownMappers中查找是否已经注册了,如果没有注册直接抛出异常,注册Mapper接口是在初始化Mybatis配置文件时必须就要完成的工作,不能在调用getMapper的时候再动态去注册
    final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
    if (mapperProxyFactory == null)
      throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
    try {

      return mapperProxyFactory.newInstance(sqlSession);
    } catch (Exception e) {
      throw new BindingException("Error getting mapper instance. Cause: " + e, e);
    }
  }

进入newInstance方法

  public T newInstance(SqlSession sqlSession) {
    //封装了一个MapperProxy对象,即组合模式,为了解耦,我们一般能不用继承就不用继续,尽量使用组合,这里MapperProxy是实现了InvocationHandler接口的类
    final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
    return newInstance(mapperProxy);
  }

newInstance(mapperProxy) 得到Mapper接口的代理对象

  @SuppressWarnings("unchecked")
  protected T newInstance(MapperProxy<T> mapperProxy) {
    return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
  }

到现在,如何得到Mapper接口的代理对象的流程就走完了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值