Mybatis如何执行一个SQL命令

平时我们在spring中用Mybatis的时候,都是用一个Mapper接口,然后通过xml或者注解进行配置。

ServiceImpl

    @Override
    public List<Map<String, Object>> getSignImgs(Map<String, Object> params) {
        return modulesMapper.getSignImgs(params);
    }

ModulesMapper

    @Select("select * from imgs")
    List<Map<String, Object>> getSignImgs(Map<String, Object> params);

这是Spring中配置Mybatis之后的调用。
但是,ModulesMapper是一个接口,背后又是如何实现调用getSignImgs方法的。
我们也知道Mybatis背后偶肯定使用动态代理去实现接口的,我们剥离spring重新看Mybatis的使用方法。

SqlSessionFactory factory = ... // 获取SqlSessionFactory的方法
SqlSession session  = factory.openSession(); // 创建一个session
ModulesMapper modulesMapper = session.getMapper(ModulesMapper.class); // session 通过动态代理获取modulesMapper的实现类

继续看SqlSession的源码
SqlSessionTemplate

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

Configuration

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

MapperRegistery

  public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
    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);
    }
  }

MapperProxyFactory

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

 public T newInstance(SqlSession sqlSession) {
 	//这里mapperInterface就是定义的Mapper接口,methodCache就是通过注解或者xml配置获取的方法cache,这里
 	//不继续展开其实怎么获取的
   final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache); 
   return newInstance(mapperProxy);
 }

整合一下,我们所知道的,对于Proxy的常用代理实现。

  1. 已经有类实现了某个接口,将该类实例化,通过反射获取该类的接口,在Proxy中实现其用法,可以在原有的方法上下添加操作,InvocationHandler 的实现中需要对原对象进行invoke操作。
  2. 只是对接口进行动态代理的实现,例如Mybatis中的实现,在Proxy中直接获取Class对象,不需要用到反射,开始并没有创建实例,InvocationHandler中不需要invoke。

列上代码,看一下区别

interface Ptest{
    void test();
}

class PtestImpl implements Ptest{
    @Override
    public void test() {
        System.out.println("原本的方法");
    }
}

class ProxyTest {
    public static void main(String[] args) {
        Ptest ptest = new PtestImpl();
        Ptest p2 = (Ptest) Proxy.newProxyInstance(ptest.getClass().getClassLoader(), ptest.getClass().getInterfaces(), (proxy, method, args1) -> {
            System.out.println("动态代理");
            return method.invoke(ptest, args1);
        });
        p2.test();
    }
}


class ProxyTest2 {
    public static void main(String[] args) {
        Ptest p2 = (Ptest) Proxy.newProxyInstance(ProxyTest2.class.getClassLoader(), new Class[]{Ptest.class}, (proxy, method, args1) -> {
            System.out.println("动态地生成对象,为接口的方法做了实现");
            return proxy;
        });
        p2.test();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Cofer_Yin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值