当前位置: 首页 > article >正文

27. 什么是MyBatis的动态代理机制?如何生成Mapper接口的实现类?

MyBatis 的动态代理机制是指 MyBatis 在运行时通过 Java 的动态代理技术,为 Mapper 接口生成具体的实现类,这些实现类会将接口方法映射到对应的 SQL 语句,并执行数据库操作。通过这种机制,开发者只需要定义接口方法,无需手动编写实现类,MyBatis 会自动生成这些实现类,并将接口方法与 SQL 语句关联起来。

MyBatis 动态代理的工作原理

  1. 定义 Mapper 接口:开发者定义一个接口,该接口中的方法对应数据库操作,比如查询、插入、更新、删除等。

  2. 配置 SQL 映射:使用 XML 映射文件或注解,将接口方法与具体的 SQL 语句进行映射。

  3. 运行时生成代理对象:在应用运行时,MyBatis 通过 Java 的动态代理机制为 Mapper 接口生成一个代理对象(Proxy),这个代理对象内部实现了接口的所有方法,并在每个方法中执行相应的 SQL 语句。

  4. 执行数据库操作:当调用 Mapper 接口的方法时,代理对象会拦截这个调用,执行与方法对应的 SQL 语句,并将结果返回给调用者。

如何生成 Mapper 接口的实现类?

MyBatis 通过动态代理机制自动生成 Mapper 接口的实现类。这种实现方式主要依赖于 Java 的 Proxy 类和 InvocationHandler 接口。

1. 定义 Mapper 接口

首先,定义一个 Mapper 接口,该接口包含数据库操作的方法。例如,定义一个 UserMapper 接口:

public interface UserMapper {
    User selectUserById(int id);
    List<User> selectAllUsers();
}

2. 配置 SQL 映射

通过 XML 文件或注解,将 Mapper 接口的方法与 SQL 语句进行映射。下面是一个 XML 映射文件的例子:

<mapper namespace="com.example.mapper.UserMapper">
    <select id="selectUserById" resultType="User">
        SELECT * FROM user WHERE id = #{id}
    </select>
​
    <select id="selectAllUsers" resultType="User">
        SELECT * FROM user
    </select>
</mapper>

3. 使用 SqlSession 获取 Mapper 实现类

MyBatis 提供了 SqlSession 接口,通过 SqlSessiongetMapper 方法,可以获取 Mapper 接口的实现类(即代理对象)。这个实现类是 MyBatis 在运行时通过动态代理生成的。

try (SqlSession session = sqlSessionFactory.openSession()) {
    UserMapper userMapper = session.getMapper(UserMapper.class);
    User user = userMapper.selectUserById(1);
    List<User> users = userMapper.selectAllUsers();
}
  • getMapper(Class<T> type):这个方法会返回一个实现了 UserMapper 接口的代理对象,开发者可以像调用普通 Java 对象的方法一样,调用 Mapper 接口的方法。

4. 动态代理的内部工作机制

MyBatis 通过 Java 的 Proxy.newProxyInstance() 方法生成 Mapper 接口的代理对象。其工作原理如下:

  1. 获取 Mapper 接口的代理对象:当 getMapper 方法被调用时,MyBatis 使用 Proxy.newProxyInstance() 方法生成 Mapper 接口的代理对象。

  2. 实现 InvocationHandler:代理对象使用了 InvocationHandler 接口,该接口的 invoke 方法会被调用,用于处理代理对象的方法调用。

  3. 执行 SQL 语句:在 invoke 方法中,MyBatis 会根据方法名称查找对应的 SQL 语句,使用 SqlSession 执行这个 SQL,并将结果封装为对应的 Java 对象返回。

public class MapperProxy<T> implements InvocationHandler {
    private final SqlSession sqlSession;
    private final Class<T> mapperInterface;
​
    public MapperProxy(SqlSession sqlSession, Class<T> mapperInterface) {
        this.sqlSession = sqlSession;
        this.mapperInterface = mapperInterface;
    }
​
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 查找对应的SQL语句,并执行
        String methodName = method.getName();
        String statementId = mapperInterface.getName() + "." + methodName;
        // 根据方法返回类型,选择相应的查询操作
        if (method.getReturnType().equals(List.class)) {
            return sqlSession.selectList(statementId, args != null ? args[0] : null);
        } else {
            return sqlSession.selectOne(statementId, args != null ? args[0] : null);
        }
    }
}

上面的 MapperProxy 是 MyBatis 生成的代理对象的工作示意。实际的 MyBatis 实现比这个例子更复杂,但核心思想类似。

5. 小结

  • 动态代理机制:MyBatis 通过 Java 的动态代理机制,在运行时为 Mapper 接口生成实现类(代理对象),这些实现类负责将接口方法映射到 SQL 语句并执行数据库操作。

  • 获取代理对象:通过 SqlSession.getMapper() 方法获取 Mapper 接口的代理对象,开发者可以直接调用接口方法来执行数据库查询。

  • 内部工作原理:MyBatis 使用 InvocationHandler 接口的 invoke 方法拦截对 Mapper 接口方法的调用,根据方法名称找到对应的 SQL 语句并执行。

MyBatis 的这种动态代理机制极大地简化了数据访问层的开发,使得开发者只需专注于接口的设计和 SQL 语句的编写,而不需要关心具体的实现细节


http://www.kler.cn/a/303906.html

相关文章:

  • 【CVPR2024】2024年CVPR的3D 目标检测的综述(还在补充中)
  • Elasticsearch基本概念及使用
  • vivo 游戏中心包体积优化方案与实践
  • Spring MVC 与 JSP 数据传输
  • 利用滑动窗口解题
  • MySQL45讲 第二十讲 幻读是什么,幻读有什么问题?
  • DoS、DDoS、DRDoS 攻击
  • CRACO 快速使用
  • 初始爬虫5
  • Linux 挂载磁盘与开机自动挂载操作指南
  • Vue 2 生命周期详解
  • 在Ubuntu 18.04上安装Nginx的方法
  • Probabilistic Embeddings for Cross-Modal Retrieval 论文阅读
  • C++string模拟实现
  • Llama Factory :百种以上语言模型的统一高效微调框架
  • UDP聊天室项目
  • 若依系统(Security)增加微信小程序登录(自定义登录)
  • nginx部署时的路径配置问题
  • 网络安全要点总结
  • 第四届长城杯-misc
  • 如何使用命令安装android的.aab包
  • Cesium 问题:视角漫游时添加的无人机模型飞行时有抖动
  • 隧道代理的原理及其挑选指南
  • 828华为云征文 | Flexus X实例在华为云EulerOS环境中部署堡垒机Jumpserver的详细指南
  • JS获取页面中video标签视频的封面和时长
  • 代理IP池纯净度对数据抓取有影响吗?