深入浅出MyBatis:Mapper接口的工作原理与使用流程
目录
前言
一、Mapper接口的本质
二、核心工作原理:动态代理
1.代理对象生成流程
2. 核心组件协作
三、完整使用流程
1.创建数据库
2.创建一个Maven项目
3.依赖导入
4.创建MyBatis核心配置文件
5.创建Student实体类
6.编写Mapper映射文件
7.编写测试类
总结
前言
MyBatis作为Java生态中广泛使用的持久层框架,主要用途是代替JDBC来操作数据库,其核心设计思想是将SQL与Java代码解耦。而Mapper接口正是实现这一理念的关键桥梁——它让我们仅需定义Java接口,即可优雅地操作数据库,彻底告别传统JDBC的模板式代码
一、Mapper接口的本质
Mapper接口是一个普通的Java接口,其中声明了数据库操作方法:
package com.module.mapper;
import com.module.pojo.Student;
import java.util.List;
public interface StudentMapper {
//定义抽象方法
public List
}
关键点:接口本身没有实现类!MyBatis通过动态代理在运行时生成实现对象
二、核心工作原理:动态代理
1.代理对象生成流程
当我们调用 Mapper 接口中的方法时,MyBatis 并不会直接让我们去实现这个接口,而是通过动态代理的方式为其生成一个代理对象。这个代理对象会拦截所有对 Mapper 接口方法的调用,从而完成后续的数据库操作。
2. 核心组件协作
MapperProxy:这是 MyBatis 框架中实现了 JDK 动态代理InvocationHandler接口的类。当通过session.getMapper(StudentMapper.class)获取代理对象时,MyBatis 会创建MapperProxy实例作为调用处理器,它会拦截 Mapper 接口方法的调用,进而协调后续的 SQL 执行流程。
MapperMethod:同样是 MyBatis 自定义的 Java 类,用于封装 Mapper 接口方法对应的 SQL 操作信息,包括 SQL 类型(SELECT/INSERT 等)、参数处理规则、结果转换逻辑等,是连接接口方法与底层 SQL 执行的关键桥梁。
MappedStatement:存储XML/注解中的SQL元数据。映射文件中定义了与数据库操作相关的 SQL 语句、参数映射、结果集映射等信息。MyBatis 会根据 Mapper 接口的全限定名去寻找对应的映射文件,或者通过注解的方式在接口方法上直接定义 SQL 语句,实现接口方法与 SQL 操作的绑定。
当代理对象拦截到方法调用后,会根据方法名、参数等信息,从映射文件或注解中找到对应的 SQL 语句。然后,MyBatis 会处理参数,将其正确地传递到 SQL 语句中,执行 SQL 操作,并对返回的结果集进行处理,按照映射规则转换为对应的 Java 对象返回给调用者。
这三个组件形成了MyBatis的执行链骨架。MapperProxy是入口,MapperMethod是转换引擎,MappedStatement是操作蓝图。它们这均属于 MyBatis 框架的源码实现,大家如果感兴趣可以等我后面出一篇三大核心组件的协作关系说明文章,本篇文章不再赘述。
三、完整使用流程
1.创建数据库
-- 创建一个学生表,自行填入相应数据
CREATE TABLE `students` (
`stu_id` int(10) NOT NULL AUTO_INCREMENT,
`stu_name` varchar(32) NOT NULL,
`stu_nickname` varchar(32) DEFAULT NULL,
`stu_age` int(10) DEFAULT NULL,
`stu_sex` varchar(8) DEFAULT NULL,
PRIMARY KEY (`stu_id`)
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8
2.创建一个Maven项目
然后点击创建,我用的是Idea2024,大家版本不同可能相应的UI页面会有不同。总之就是要创建一个Maven项目,目录结构可以参考图片。
3.依赖导入
这里导入的依赖需要与自己环境版本匹配
4.创建MyBatis核心配置文件
在resource文件夹下创建Mybatis_config.xml,我在这里开启了小驼峰自动映射,方便后面Java类属性与数据库字段的自动映射,这样我们就不用再进行手动映射。
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
5.创建Student实体类
在pojo包下创建Student类,属性最好采用小驼峰方式命名与数据库字段相对应,方便MyBatis自动映射,需要手动创建映射关系。
public class Student {
private int stuId;
private String stuName;
private String stuNickname;
private int stuAge;
private String stuSex;
}
//有参、无参构造方法,getter()、setter()方法自动生成即可
6.编写Mapper映射文件
(1)在src/main/java/com/module/mapper包下编写StudentMapper接口
package com.module.mapper;
import com.module.pojo.Student;
import java.util.List;
public interface StudentMapper {
//定义抽象方法:两个测试方法
public List
public List
}
(2)在src/main/resources/com/module/mapper目录下编写StudentMapper.xml。(可以抽象理解为上面StudentMapper接口的实现类)
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
select stu_id as stuId,stu_name as stuName,stu_nickname as stuNickname,stu_age as stuAge,stu_sex as stuSex from Students
select * from Students
7.编写测试类
我采用单元测试,在src/test/java/com/module/test1创建一个测试类。
package com.module.test1;
import com.module.mapper.StudentMapper;
import com.module.pojo.Student;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class Test1 {
InputStream is = null;
SqlSession session = null;
StudentMapper mapper = null;
//在测试代码之前执行
@Before
public void beforMethod(){
//1.加载mybatis主配置文件
try {
is = Resources.getResourceAsStream("Mybatis_config.xml");
} catch (IOException e) {
e.printStackTrace();
}
//2.创建sqlSessionFactoryBuilder
SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
//3.创建sqlSessionFactory
SqlSessionFactory factory = sqlSessionFactoryBuilder.build(is);
//4.创建sqlSession,类似jdbc的Connection与Statment的结合
session = factory.openSession();
//5.加载映射器,同时创建代理对象
mapper = session.getMapper(StudentMapper.class);
}
//在测试代码之后执行
@After
public void afterMethod(){
//7.关闭
session.close();
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void test1(){
//6.调用方法
List
for (Student stu : resStudent){
System.out.println(stu);
}
}
@Test
public void test2(){
//6.调用方法
List
for (Student stu : resStudent){
System.out.println(stu);
}
}
}
总结
MyBatis通过动态代理技术将Mapper接口转化为可执行SQL的代理对象,实现了:
接口方法与SQL操作的透明映射
完全的数据库操作类型安全
优雅的SQL与代码分离架构
最佳实践建议:对于简单查询优先使用注解,复杂动态SQL使用XML配置,两者结合可获得最佳开发体验。
本文主要为大家介绍了Mapper的基本工作流程及原理,并提供了一个完整的使用流程,希望对大家能有所帮助。
通过理解Mapper背后的运行机制,开发者能够更高效地利用MyBatis构建健壮的数据访问层,让数据库交互变得简洁而强大。
世界杯直播