不学无数——Mybatis自动映射器Mapper原理分析

简介: 在使用MyBatis时,有时候会想,为什么只写一个接口没有编写任何的实现类,但是就能返回接口的实例,并且调用接口的方法返回数据库中的数据?此时脑海中浮现了写动态代理时候的记忆,记得动态代理也是接管了接口,不需要实际的代理角色。

在使用MyBatis时,有时候会想,为什么只写一个接口没有编写任何的实现类,但是就能返回接口的实例,并且调用接口的方法返回数据库中的数据?此时脑海中浮现了写动态代理时候的记忆,记得动态代理也是接管了接口,不需要实际的代理角色。然后经过源码的Debug发现果然是运用了动态代理的技术。如果对于动态代理技术不熟悉的同学可以看不学无数—动态代理

Mybatis自动映射器Mapper的源码分析

首先我们想Debug源码就得写一个测试类如下:

@Autowired
private SqlSessionFactory sqlSessionFactory;

@Test
public void testMybatis(){
    SqlSession sqlSession = sqlSessionFactory.openSession();
    TBapCheckPtsTranscdMapper mapper = sqlSession.getMapper(TBapCheckPtsTranscdMapper.class);
    TAmsAcPmtDtlPo tAmsAcPmtDtlPo= new TAmsAcPmtDtlPo();
    mapper.queryTransCdByType(tAmsAcPmtDtlPo);
}

Mapper是这样的

public interface TBapCheckPtsTranscdMapper {

    List<Map<String,String>> queryTransCdByType(TAmsAcPmtDtlPo tAmsAcPmtDtlPo);
    
}

首先先弄明白如何得到的接口的实际对象,由此Debug进去。

TBapCheckPtsTranscdMapper mapper = sqlSession.getMapper(TBapCheckPtsTranscdMapper.class);

然后进行Debug源码,发现在MapperProxyFactory中,返回了代理对象。

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

然后发现在执行接口的方法的时候进入到了代理MapperProxy

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
  //诸如hashCode()、toString()、equals()等方法,将target指向当前对象this
  if (Object.class.equals(method.getDeclaringClass())) {
    return method.invoke(this, args);
  } else if (isDefaultMethod(method)) {
    return invokeDefaultMethod(proxy, method, args);
  }
} catch (Throwable t) {
  throw ExceptionUtil.unwrapThrowable(t);
}
final MapperMethod mapperMethod = cachedMapperMethod(method);
return mapperMethod.execute(sqlSession, args);
}

自己写一个小例子

首先自己定义个实体类

public class User {
    private Integer id;
    private String name;
    private String age;
    -----get,set方法
}

然后Mapper接口如下

public interface UserMapper {
    public User findUserById(Integer id);
}

代理类如下

public class MapperProxy implements InvocationHandler {

    @SuppressWarnings("unchecked")
    public <T> T newInstance(Class<T> clz) {
        return (T) Proxy.newProxyInstance(clz.getClassLoader(), new Class[] { clz }, this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if (Object.class.equals(method.getDeclaringClass())) {
            try {
                // 诸如hashCode()、toString()、equals()等方法,将target指向当前对象this
                return method.invoke(this, args);
            } catch (Throwable t) {
            }
        }
        //后面的xml解析之类的就先不模拟,在这直接返回数据
        return new User((Integer) args[0], "zhangsan", "18");
    }
}

测试如下

public static void main(String[] args) {
    ClassLoader classLoader = UserMapper.class.getClassLoader();
    MapperProxy mapperProxy = new MapperProxy();
    //通过代理生成接口的实例对象
    UserMapper mapper = (UserMapper) Proxy.newProxyInstance(classLoader, new Class[]{UserMapper.class},mapperProxy);
    User user = mapper.findUserById(10000);
    System.out.println("ID:" + user.getId());
    System.out.println("Name:" + user.getName());
    System.out.println("Age:" + user.getAge());
}

打印如下

ID:10000
Name:zhangsan
Age:18
Practice.Day09.MapperProxy@24d46ca6

相关文章
|
2月前
|
SQL XML Java
mybatis-源码深入分析(一)
mybatis-源码深入分析(一)
|
19天前
|
SQL Java 数据库连接
mybatis使用四:dao接口参数与mapper 接口中SQL的对应和对应方式的总结,MyBatis的parameterType传入参数类型
这篇文章是关于MyBatis中DAO接口参数与Mapper接口中SQL的对应关系,以及如何使用parameterType传入参数类型的详细总结。
27 10
|
2月前
|
SQL XML Java
mybatis复习04高级查询 一对多,多对一的映射处理,collection和association标签的使用
文章介绍了MyBatis中高级查询的一对多和多对一映射处理,包括创建数据库表、抽象对应的实体类、使用resultMap中的association和collection标签进行映射处理,以及如何实现级联查询和分步查询。此外,还补充了延迟加载的设置和用法。
mybatis复习04高级查询 一对多,多对一的映射处理,collection和association标签的使用
|
24天前
|
SQL XML Java
Mybatis的原理和MybaitsPlus
这篇文章对比分析了Mybatis和Mybatis Plus的特点与底层实现机制,探讨了两者之间的差异及各自的优势。
39 0
|
3月前
|
SQL Java 数据库连接
Mybatis系列之 Error parsing SQL Mapper Configuration. Could not find resource com/zyz/mybatis/mapper/
文章讲述了在使用Mybatis时遇到的资源文件找不到的问题,并提供了通过修改Maven配置来解决资源文件编译到target目录下的方法。
Mybatis系列之 Error parsing SQL Mapper Configuration. Could not find resource com/zyz/mybatis/mapper/
|
2月前
|
SQL XML Java
mybatis :sqlmapconfig.xml配置 ++++Mapper XML 文件(sql/insert/delete/update/select)(增删改查)用法
当然,这些仅是MyBatis功能的初步介绍。MyBatis还提供了高级特性,如动态SQL、类型处理器、插件等,可以进一步提供对数据库交互的强大支持和灵活性。希望上述内容对您理解MyBatis的基本操作有所帮助。在实际使用中,您可能还需要根据具体的业务要求调整和优化SQL语句和配置。
43 1
|
4月前
|
SQL Java 数据库连接
idea中配置mybatis 映射文件模版及 mybatis plus 自定义sql
idea中配置mybatis 映射文件模版及 mybatis plus 自定义sql
79 3
|
4月前
|
SQL Java 数据库连接
springboot~mybatis-pagehelper原理与使用
【7月更文挑战第15天】MyBatis-PageHelper是用于MyBatis的分页插件,基于MyBatis的拦截器机制实现。它通过在SQL执行前动态修改SQL语句添加LIMIT子句以支持分页。使用时需在`pom.xml`添加依赖并配置方言等参数。示例代码: PageHelper.startPage(2, 10); List&lt;User&gt; users = userMapper.getAllUsers(); PageInfo&lt;User&gt; pageInfo = new PageInfo&lt;&gt;(users); 这使得分页查询变得简单且能获取总记录数等信息。
|
3月前
|
XML Java 数据库连接
Mybatis 模块拆份带来的 Mapper 扫描问题
Mybatis 模块拆份带来的 Mapper 扫描问题
43 0
|
4月前
|
SQL Java 数据库连接
Java面试题:简述ORM框架(如Hibernate、MyBatis)的工作原理及其优缺点。
Java面试题:简述ORM框架(如Hibernate、MyBatis)的工作原理及其优缺点。
68 0