MyBatis 的 Mapper 映射的内部组成及其实现

本文详细介绍了MyBatis的Mapper映射的内部组成,包括MappedStatement、SqlSource和BoundSql三个关键部分。MappedStatement存储了SQL配置、ID、缓存信息等。SqlSource用于根据参数组装SQL,而BoundSql则包含了SQL、参数对象和参数映射。在参数处理中,MyBatis会根据参数类型进行转换。Mapper映射的实现依赖于动态代理,MapperProxyFactory生成动态代理对象以实现接口方法的调用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Mapper 映射的内部组成

一般而言,一个映射器是由3部分组成的:

  • MappedStatement
    它保存映射器的一个节点(select | insert | delete | update)。包括许多我们配置的 SQL、SQL 的 id、缓存信息、resultMap、parameterType、resultType 和 languageDriver 等重要的内容。
  • SqlSource
    它是提供 BoundSql 对象的地方,是 MappedStatement 的一个属性。
  • BoundSql
    它是建立 SQL 和参数的地方。它有3个常用的属性:SQL、parameterObject 和 parameterMappings。

映射器的内部组成如图所示:
Mapper的内部组成

MappedStatement 对象涉及的东西较多,我们一般不去修改它,因为容易产生不必要的错误。
SqlSource 是一个接口,它的主要作用是根据参数和其他的规则组装SQL。
对于参数和 SQL 而言,主要的规则都反映在 BoundSql 类对象上,BoundSql 会提供3个主要的属性:parameterMappings、parameterObject 和 sql

  • parameterObject
    它为参数本身,它有如下的规则:

    1. 传递简单对象时,如int类型,MyBatis会把参数变为其对应的包装类Integer对象传递。类似的long、float也是如此。
    2. 如果传递的是POJO或者Map,则类型不变。
    3. 可以传递多个参数。如果没有@Param注解,那么MyBatis会把parameterObject变成一个Map<String, Object>对象,键值类似{“1”: p1, “2”: p2, “3”: p3…, “param1”: p1, “param2”: p2, “param3”: p3…},所以我们可以使用#{paramN}或者是#{N}去引用第N个参数;如果使用@param注解,MyBatis也会把parameterObject变为一个Map<String, Object>对象,只是把纯数字的键置换成@param注解的键,如@param(“key1”) String p1, @param(“key2”) int p2, @param(“key3”) Role p3, 那么这个parameterObject对象就是一个Map<String, Object>对象,键值包含{“key1”: p1, “key2”: p2, “key3”: p3, “param1”: p1, “param2”: p2, “param3”: p3}。
  • parameterMappings
    它是一个List,每一个元素都是ParameterMapping的对象,这个对象会描述我们的参数。参数包括属性、名称、表达式、javaType、jdbcType、typeHandler等重要信息。通过它可以实现参数和SQL的结合,以便PreparedStatement能够通过它找到parameterObject对象的属性并设置参数,使得程序准确运行。

  • sql
    sql属性就是我们书写在映射器里面的一条SQL。

Mapper 映射的实现

Mapper映射是通过动态代理来实现的,下面是MapperProxyFactory的部分源码:

public class MapperProxyFactory<T> {

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

    public T newInstance(SqlSession sqlSession) {
        final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
        return newInstance(mapperProxy);
    }

}

在这里可以看到动态代理对接口的绑定,它的作用就是生成动态代理对象(占位),而代理的方法则被放到了MapperProxy类中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值