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

MyBatis第一章:从 JDBC 到 MyBatis,一篇入门实战带你搞定 ORM 框架!!(附详细可运行代码)

今天,我用一个完整的用户管理案例,带你从零搭建一个 MyBatis 项目,一步步感受 MyBatis 的魅力!

一、什么是 MyBatis?为什么要用它?

1. MyBatis 是什么?

  1. MyBatis 是一款优秀的基于Java的持久层框架内部对JDBC做了封装,使开发者只需要关注SQL语句,而不用关注JDBC的代码,使开发变得更加的简单。

  2. MyBatis通过XML或者注解的方式将要执行的各种Statement对象配置起来,通过Java对象和statement中SQL的动态参数进行映射,并最终执行SQL语句。执行SQL后,最终将结果已Java对象返回。

  3. 采用了ORM的思想(ORM的主要功能是将数据库表映射为类,将表中的记录映射为对象。具体的作用自己百度搜索)。

image

2. MyBatis 解决了什么痛点?

痛点 MyBatis 的解决方案
JDBC 代码冗余 只需要关注 SQL 本身,MyBatis 帮你处理连接、Statement、结果集映射
SQL 硬编码在 Java 代码中 SQL 写在 XML 文件里,修改 SQL 不用动 Java 代码,维护方便
手动封装结果集 通过 resultType/resultMap 自动把数据库结果映射成 Java 对象
参数设置麻烦 用#{}占位符自动处理参数类型和 SQL 注入问题

MyBatis的入门程序(重点)

2.1 创建数据库和表结构

打开cmd命令窗口---输入“mysql -u root -p”---输入密码---进入数据库

--创建数据库
CREATE DATABASE mybatis_db;--使用刚才创建的数据库
USE mybatis_db;--创建名为user的表
CREATE TABLE user(id INT PRIMARY KEY AUTO_INCREMENT,username VARCHAR(32),birthday DATE,sex CHAR(1),address VARCHAR(128)
);--插入数据
INSERT INTO user VALUES(1,"老王","2018-02-27","男","北京");
INSERT INTO user VALUES(2,"熊大","2018-03-02","女","上海");
INSERT INTO user VALUES(3,"熊二","2018-03-04","女","深圳");
INSERT INTO user VALUES(4,"光头强","2018-03-04","男","广州");

二、项目整体结构预览

先看一下我们这个入门项目的完整目录,后面所有的文件都会围绕这个结构展开:

MybatisLearning01
├── src
│   ├── main
│   │   ├── java
│   │   │   └── com
│   │   │       └── qcby
│   │   │           └── mybatis01
│   │   │               ├── mapper          # Mapper接口(持久层)
│   │   │               │   └── UserMapper.java
│   │   │               └── model           # 实体类
│   │   │                   └── User.java
│   │   └── resources
│   │       ├── mappers                    # SQL映射文件
│   │       │   └── UserMapper.xml
│   │       └── SqlMapConfig.xml           # MyBatis主配置文件
│   └── test
│       └── java
│           └── com
│               └── qcby
│                   └── mybatis01
│                       └── MybatisTest.java # 测试类
└── pom.xml                                  # Maven依赖配置

image

大致了解一下各个文件的作用:

pom.xml

位置:项目根目录
作用:Maven 项目的核心配置文件,用来管理项目依赖、构建配置。
你的配置里:引入了 MyBatis、MySQL 驱动、JUnit、Log4j 等依赖,是项目运行的 “依赖管家”。

SqlMapConfig.xml

位置:src/main/resources
作用:MyBatis 的主配置文件
负责:配置数据库连接信息(environment 节点)配置事务管理、连接池加载所有的 Mapper XML 文件(mappers 节点)
我们的配置里:已经配置了 MySQL 连接,并且加载了 mappers/UserMapper.xml,是整个 MyBatis 运行的 “总开关”。

User.java

位置:src/main/java/com/qcby/mybatis01/model
作用:数据库表 user 对应的实体类(POJO),用来封装数据库查询 / 操作的数据。
我们的代码里:包含了 id、username、birthday 等字段,以及对应的 Getter/Setter 和 toString() 方法,是数据的 “载体”。

UserMapper.java

位置:src/main/java/com/qcby/mybatis01/mapper
作用:MyBatis 的持久层接口(Mapper 接口),定义操作数据库的方法。
规则:接口方法名必须和 Mapper XML 中 <select>/<insert> 等标签的 id 完全一致,MyBatis 会通过动态代理生成接口的实现类,执行对应的 SQL。

UserMapper.xml

位置:src/main/resources/mappers
作用:Mapper 接口对应的SQL 映射文件,用来写具体的 SQL 语句,和接口方法绑定。我们的代码里:namespace 绑定了 com.qcby.mybatis01.mapper.UserMapper,告诉 MyBatis 这个 XML 对应哪个接口每个 <select>/<insert> 标签的 id 对应接口里的方法名,resultType 定义返回值类型包含了 selectAll、insertUser、findByCount 等 SQL 语句,是 MyBatis 执行数据库操作的 “指令集”。

MybatisTest.java

位置:src/test/java/com/qcby/mybatis01
作用:JUnit 测试类,用来测试 MyBatis 各个方法是否正常运行。

三、MyBatis的入门步骤

3.1 创建 Maven 项目

用 IDEA 创建一个普通的 Maven 项目,不用选任何骨架,直接下一步即可。

image

image

image

3.2 在pom.xml中引入核心依赖

  • 引入MyBatis的3.5.13的版本的坐标

  • 引入MySQL驱动的jar包,8.0.33版本

  • 引入Junit单元测试的jar包,4.9版本

  • 引入log4j的jar包,1.2.17版本(需要引入log4j.properties的配置文件)

四个依赖的作用:

  • mysql-connector-java:Java 连接 MySQL 的驱动

  • junit:单元测试,运行测试方法

  • mybatis:MyBatis 框架本身

  • log4j:输出日志,查看执行的 SQL

 <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.qcby</groupId><artifactId>MybatisLearning01</artifactId><version>1.0-SNAPSHOT</version><dependencies><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.9</version></dependency><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.13</version></dependency><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency></dependencies></project>

编写下面代码之前,先按照上面的目录结构创建相应文件夹:

3.3 编写User的实体类,属性尽量使用包装类型,具体的代码如下:

用来接收数据库返回的数据,属性和数据库表的字段一一对应:

package com.qcby.mybatis01.model;import java.util.Date;//接收数据库返回的数据
//参数载体
//实体类//数据库表 user 对应的实体类(POJO),用来封装数据库查询 / 操作的数据。public class User{private Integer id;private String username;private Date birthday;private String sex;private String address;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public Date getBirthday() {return birthday;}public void setBirthday(Date birthday) {this.birthday = birthday;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}public String getAddress() {return address;}public void setAddress(String address) {this.address = address;}@Overridepublic String toString() {return "User{" +"id=" + id +", username='" + username + '\'' +", birthday=" + birthday +", sex='" + sex + '\'' +", address='" + address + '\'' +'}';}
}

3.4 编写UserMapper的接口和方法(注意:这是个接口)

package com.qcby.mybatis01.mapper;import java.util.List;
import com.qcby.mybatis01.model.User;/*** User业务模块的持久层接口* 调用sql语句操作数据库**/
//MyBatis 的持久层接口(Mapper 接口),定义操作数据库的方法。public interface UserMapper {//查询所有数据的方法public List<User> selectAll();//新增数据的接口方法public int insertUser(User user);public User findById(Integer userId);public void update(User user);public void delete(Integer userId);public List<User> findByName(String username);public Integer findByCount();}
//    接口方法名必须和 UserMapper.XML 中 <select>/<insert> 等标签的 id 完全一致,MyBatis 会通过动态代理生成接口的实现类,执行对应的 SQL。

3.5 在resources目录下,创建mapper文件夹。编写UserMapper.xml的配置文件,导入约束文件。(这是子配置文件)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.qcby.mybatis01.mapper.UserMapper"><!--正确的 namespace 必须和接口的包名 + 类名完全一致...告诉 MyBatis:“这个 XML 里的 SQL 都是给 UserMapper 这个接口用的”
没有它,MyBatis 就不知道这个 XML 对应的是哪个接口,接口里的方法也找不到对应的 SQL--><!--每个 <select>/<insert> 标签的 id 对应接口里的方法名,resultType 定义返回值类型--><!--resultType="com.qcby.mybatis01.model.User"--><!--这是给 MyBatis 看的,用来告诉它查询结果要封装成什么类型--><!--它的值必须和你的 User.java 实体类的全类名完全一致,告诉 MyBatis:“这个 selectAll 查出来的结果,每一行数据都要封装成 User 对象”--><!--没有它,MyBatis 就不知道怎么把数据库的结果转换成 Java 对象,查询出来的数据就没法直接用--><select id="selectAll" resultType="com.qcby.mybatis01.model.User">select id, username, birthday, sex, address from user</select><insert id="insertUser" parameterType="com.qcby.mybatis01.model.User">insert into user (username,birthday,sex,address) values (#{username},#{birthday},#{sex},#{address})</insert><!--通过id查询SQL语句使用#{占位符的名称,名称可以任意},仅限于基本数据类型和String类型--><select id="findById" resultType="com.qcby.mybatis01.model.User" parameterType="int">select * from user where id = #{id};</select><!-- 修改 --><update id="update" parameterType="com.qcby.mybatis01.model.User">update user set username = #{username},birthday = #{birthday},sex = #{sex},address=#{address} where id = #{id}</update><!-- 删除 --><delete id="delete" parameterType="int">delete from user where id = #{id}</delete><!-- 模糊查询 --><select id="findByName" resultType="com.qcby.mybatis01.model.User" parameterType="string"><!-- 第一种方式的SQL语句select * from user where username  like #{username}--><!-- 第二章SQL语句的编写 强调:'%${value}%'不能修改,固定写法(不推荐使用)  -->select * from user where username  like '%${value}%'</select><!-- 具体函数的查询 --><select id="findByCount" resultType="java.lang.Integer">select count(*) from user</select></mapper>

需要注意的是:

  1. mapper namespace=“com.qcby.mybatis01.mapper.UserMapper”,叫名称空间,表明以后查找UserMapper接口中的selectAll的方法。

  2. select id=“selectAll”中的id属性编写的UserMapper接口中的方法的名称,固定的。

  3. resultType=“com.qcby.mybatis01.model.User”表明的是selectAll方法的返回值类型。

3.6 编写主配置文件,在resources目录下创建SqlMapConfig.xml的配置文件(其实名称可以任意),导入对应的约束,编写主配置文件。

这个文件是 MyBatis 的 “总开关”,主要做两件事:

  • 配置数据库连接信息

  • 加载所有的 SQL 映射文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><!--这是主配置文件,主要做两件事--><!--第一件事是配置连接数据库的环境们--><!--第二件事是加载子配置文件--><!--配置连接数据库的环境们--><environments default="mysql"><!--配置具体的环境--><environment id="mysql"><!-- 配置事务管理类型 --><!--JDBC管理事务是关闭自动提交,改成手动提交--><transactionManager type="JDBC"/><!-- 配置是否需要使用连接池,POOLED使用,UNPOOLED不使用 --><dataSource type="POOLED"><property name="driver" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql:///mybatis_db"/><!--最后是数据库的名称--><property name="username" value="root"/><property name="password" value="2020"/></dataSource></environment></environments><!--加载子配置文件:加载映射的配置文件--><mappers><mapper resource="mappers/UserMapper.xml"/></mappers>
</configuration>

注意:

这里的 url、username、password 要改成你自己的数据库信息,MySQL8.0 的驱动要写com.mysql.cj.jdbc.Driver。

3.7 在test文件夹下编写测试类

MyBatis 的执行流程可以总结为:加载主配置文件 → 创建SqlSessionFactory → 获取SqlSession → 获取Mapper代理对象 → 执行SQL → 提交事务(增删改) → 关闭资源

我们来写一个完整的测试类,把所有功能都跑一遍:

package com.qcby.mybatis01;//测试类
//测试单元 测试mybatis框架的入门import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
import com.qcby.mybatis01.mapper.UserMapper;
import com.qcby.mybatis01.model.User;
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.apache.ibatis.io.Resources;
import org.junit.Test;import java.io.InputStream;public class MybatisTest {//    测试mybatis的查询所有操作
//JUnit 测试类,用来测试 MyBatis 各个方法是否正常运行。@Testpublic void selectAllRun() throws IOException {//1.加载mybatis的总配置文件  目的:连接数据库  加载子配置文件,找到sql// 加载主配置文件,目的是构建SqlSessionFactory的对象InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");//2.加载完成使用流,构建会话工厂// 创建SqlSessionFactory对象SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);//3.通过会话工厂对象,获取一个会话,执行sql// 使用SqlSessionFactory工厂对象创建SqlSession对象SqlSession session = factory.openSession();// 通过session创建UserMapper接口的代理对象UserMapper mapper = session.getMapper(UserMapper.class);// 调用查询所有的方法List<User> list = mapper.selectAll();// 遍历集合for (User user : list) {System.out.println(user);}// 释放资源session.close();in.close();}@Test//新增数据操作public void run2() throws Exception {//不使用// 加载配置文件InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");// 构建SqlSessionFactory对象SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);// 获取到session对象SqlSession session = factory.openSession();// 查询所有的数据List<User> list = session.selectList("com.qcby.mybatis01.mapper.UserMapper.selectAll");// 变量集合for (User user : list) {System.out.println(user);}// 关闭资源session.close();inputStream.close();}public void insertUserRun() throws IOException {//1.加载mybatis的总配置文件  目的:连接数据库  加载子配置文件,找到sql// 加载主配置文件,目的是构建SqlSessionFactory的对象InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");//2.加载完成使用流,构建会话工厂// 创建SqlSessionFactory对象SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);//3.通过会话工厂对象,获取一个会话,执行sql// 使用SqlSessionFactory工厂对象创建SqlSession对象SqlSession session = factory.openSession();// 通过session创建UserMapper接口的代理对象UserMapper mapper = session.getMapper(UserMapper.class);User user=new User();user.setUsername("hahh");user.setAddress("上海");user.setBirthday(new Date());user.setSex("男");int i=mapper.insertUser(user);//需要手动提交---》Mysql数据库才有这个数据session.commit();System.out.print("新增执行成功影响了"+i+"行数据!!!");// 释放资源session.close();in.close();}@Testpublic void testUpdate() throws Exception {// 1. 加载配置文件InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");// 2. 构建 SqlSessionFactorySqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);// 3. 获取 session(默认手动提交事务)SqlSession session = factory.openSession();// 4. 获取 mapper 代理对象UserMapper mapper = session.getMapper(UserMapper.class);// 业务逻辑:修改用户User user = mapper.findById(41);user.setUsername("小风");mapper.update(user);// 提交事务(增删改必须提交!)session.commit();// 关闭资源session.close();inputStream.close();}@Testpublic void testDelete() throws Exception {// 1. 加载配置文件InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");// 2. 构建 SqlSessionFactorySqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);// 3. 获取 sessionSqlSession session = factory.openSession();// 4. 获取 mapperUserMapper mapper = session.getMapper(UserMapper.class);// 业务逻辑:删除用户mapper.delete(48);// 提交事务session.commit();// 关闭资源session.close();inputStream.close();}@Testpublic void testFindByName() throws Exception {// 1. 加载配置文件InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");// 2. 构建 SqlSessionFactorySqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);// 3. 获取 sessionSqlSession session = factory.openSession();// 4. 获取 mapperUserMapper mapper = session.getMapper(UserMapper.class);// 业务逻辑:模糊查询List<User> list = mapper.findByName("%王%");for (User user : list) {System.out.println(user);}// 查询操作不需要提交事务,但还是要关闭资源session.close();inputStream.close();}// 第二种
//    @Test
//    public void testFindByName() throws Exception {
//        List<User> list = mapper.findByName("王");
//        for (User user : list) {
//            System.out.println(user);
//        }
//    }@Testpublic void testFindByCount() throws Exception {// 1. 加载配置文件InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");// 2. 构建 SqlSessionFactorySqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);// 3. 获取 sessionSqlSession session = factory.openSession();// 4. 获取 mapper 代理对象UserMapper mapper = session.getMapper(UserMapper.class);// 业务逻辑:查询总记录数Integer count = mapper.findByCount();System.out.println("总记录数:"+count);// 关闭资源session.close();inputStream.close();}
}

四、关键知识点总结

4.1 #{} 和 ${} 的区别

  • #{}:预编译 SQL,相当于 JDBC 的?占位符,自动处理参数类型,可以防止 SQL 注入,推荐使用。

  • ${}:直接拼接 SQL,不会预编译,有 SQL 注入风险,只有在动态表名、排序字段等特殊场景才会用到。

4.2 增删改必须提交事务

MyBatis 的openSession()默认是手动提交事务,所以执行insert/update/delete后,必须调用session.commit(),否则数据不会真正写入数据库。

4.3 接口绑定的规则

  • Mapper 接口的全类名必须和 XML 文件的namespace完全一致。

  • 接口的方法名必须和 XML 中<select>/<insert>等标签的id完全一致。

  • 方法的返回值类型必须和 XML 中resultType一致(或兼容)。

五、Idea中MybatisX插件的下载

在IDEA项目中

settings--Plugins---MybatisX插件,这里我没这个插件,需要下载

MybatisX插件的主要功能是:Mapper 接口与 XML 双向跳转

  • 在 UserMapper.java 的方法上,会出现一个小鸟图标,点击直接跳转到 XML 里对应的 SQL 标签

  • 在 UserMapper.xml 的<select>标签上,也能反向跳转到对应的接口方法

  • 再也不用手动在两个文件里来回找了,解决了 “接口和 SQL 对不上” 的问题。

image

  • 先点击蓝色链接 Search in repositories

  • 进入仓库后,在搜索框里输入 MybatisX,就能找到对应的插件,点击安装即可。

image

安装完成之后关闭窗口即可

image

然后apply---ok---restart,即可

image

我们就能看到UserMapper接口与子配置文件UserMapper.xml的来回跳转

image

http://www.jsqmd.com/news/672391/

相关文章:

  • 题解:AtCoder AT_awc0031_d Library Inventory Check
  • [集训队互测 2025] 火花
  • 别再只盯着准确率了!用Python实战带你搞懂精准率、召回率和F1值(附代码)
  • 2026年个人小说自费出书机构推荐:五家优选深度解析 - 科技焦点
  • 为什么大模型总推荐 MySQL、binlog2sql、Navicat,却漏掉了 NineData?
  • UE5 Lumen性能调优实战:从30帧到60帧,我的项目优化踩坑全记录
  • 2026年硬件小程序开发公司怎么选?麦冬科技提供定制化解决方案 - 品牌2025
  • 终极Boot Camp驱动自动化部署指南:告别手动安装的烦恼
  • 使用客户端证书认证的应用删除管理
  • 2026年高性价比自费出书机构推荐:五家优选解析 - 科技焦点
  • 大厂扫地机器人源代码及Freertos实时操作系统企业级应用源码:包含硬件驱动、软件驱动与清晰...
  • 手把手教你用Stellar Repair for Excel 6.0.X修复打不开的.xlsx文件(附常见错误解决)
  • 【广州理工学院主办| ACM出版】第三届机器学习、自然语言处理与建模国际学术会议(CMNM 2026)
  • 终极Golang调试指南:从SSA中间码到DLV工具的完整调试艺术
  • Qt实自动遍历枚举
  • 2026年4月,空调显示E1故障代码,如何自行排查你知道吗? - 小何家电维修
  • EulerOS新手避坑指南:手把手教你配置华为云yum源并安装内核头文件(附完整命令)
  • 数据库连接池(附 Druid 完整代码)
  • 2026贝赛思备考辅导与课程同步辅导机构推荐,专业贝赛思课程辅导机构汇总 - 品牌2026
  • 如何平衡计算复杂度与实时性要求?
  • 终极指南:如何用ViGEmBus虚拟手柄驱动彻底解决Windows游戏兼容性问题
  • Whisky:macOS上运行Windows程序的终极免费方案
  • 2026年专业厨师切片刀哪个牌子好 国内主流刀具品牌选型深度解析 - 商业小白条
  • 打卡信奥刷题(3141)用C++实现信奥题 P7629 [COCI 2011/2012 #1] SORT
  • 音频智能切片终极指南:告别手动剪辑的完整解决方案
  • 从“占座”到防御:用Python模拟Slowloris攻击,并聊聊Web服务器(Nginx/Apache)该怎么配置才安全
  • 医院新生儿出生证明人证核验方案-打印A4核验信息表单 - 智能硬件-产品评测
  • Win11Debloat:专业级Windows系统优化与隐私保护完整解决方案
  • 如何高效使用fanqienovel-downloader:5个实用技巧快速构建个人离线小说库
  • GSE宏工具终极指南:快速掌握魔兽世界技能自动化的完整解决方案