云计算百科
云计算领域专业知识百科平台

MyBatis 从入门到精通

一、MyBatis 核心介绍

1.1 什么是框架

框架(Framework)是软件开发的 "半成品",它封装了基础代码并提供标准化 API,开发者基于框架开发可省去重复编码工作,大幅提升开发效率。

如果把成品软件比作装修好的新房,框架就像毛坯房 —— 提供基础结构,保证核心质量,开发者只需专注于业务逻辑(装修)即可。

1.2 框架要解决的核心问题

框架最核心的价值是技术整合与解耦。在 J2EE 体系中,技术选型多样且复杂,框架能将应用设计与底层技术实现分离,让研发聚焦于业务设计,而非技术细节。

1.3 传统 JDBC 的痛点

先看一段传统 JDBC 代码:

public class JdbcTest {
public static void main(String[] args) {
try {
//1.加载数据库驱动
Class.forName("com.mysql.jdbc.Driver");
//2.创建连接对象
String url = "jdbc:mysql://192.168.10.137:3306/ssm";
Connection connection = DriverManager.getConnection(url, "root", "1111");
String sql = "select * from account";
//3.准备PreparedStatement对象
PreparedStatement pst = connection.prepareStatement(sql);
//4.执行sql语句
ResultSet rs = pst.executeQuery();
//5.遍历结果集
while(rs.next()){
Integer id = rs.getInt("id");
String name = rs.getString("name");
Double money = rs.getDouble("money");
System.out.println(id + " " + name + " " + money);
}
//6.关闭资源
rs.close();
pst.close();
connection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}

传统 JDBC 存在三大核心问题:

  • 手动创建 / 释放数据库连接,资源管理繁琐
  • SQL 语句硬编码在代码中,维护成本高
  • 结果集解析重复且冗余,代码复用性差

1.4 MyBatis 框架概述

MyBatis 是一款优秀的持久层框架,它对 JDBC 进行封装,让开发者只需关注 SQL 本身,无需处理注册驱动、创建连接、参数设置、结果集解析等繁琐操作。

MyBatis 前身是 Apache 的 iBatis,2010 年迁移至 Google Code 并更名,核心定位是简化数据库操作,专注 SQL 层开发。

二、MyBatis 入门案例

2.1 环境准备

(1)Maven 依赖配置(pom.xml)

<?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.hg</groupId>
<artifactId>01_mybatis_HelloWorld</artifactId>
<version>1.0-SNAPSHOT</version>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>

<dependencies>
<!– MyBatis核心依赖 –>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!– MySQL驱动 –>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!– 日志依赖 –>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!– 单元测试 –>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>

<build>
<!– 加载java目录下的xml配置文件 –>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
</resources>
</build>
</project>

(2)日志配置(log4j.properties)

properties

# Global logging configuration
log4j.rootLogger=DEBUG, stdout
# Console output
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] – %m%n

2.2 核心代码实现

(1)实体类(User.java)

public class User implements Serializable {
private Integer id;
private String username;
private Date birthday;
private String sex;
private String address;

// Getter & Setter
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; }

@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\\'' +
", birthday=" + birthday +
", sex='" + sex + '\\'' +
", address='" + address + '\\'' +
'}';
}
}

(2)DAO 接口(UserMapper.java)

public interface UserMapper {
/**
* 查询所有用户
* @return 用户列表
*/
public List<User> findAll();
}

(3)Mapper 映射文件(UserMapper.xml)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!– namespace:接口全类名 –>
<mapper namespace="com.hg.dao.UserMapper">
<!–
id:接口方法名
resultType:返回值类型
–>
<select id="findAll" resultType="com.hg.pojo.User">
select * from user
</select>
</mapper>

(4)MyBatis 核心配置(mybatis-config.xml)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!– 环境配置 –>
<environments default="dev">
<environment id="dev">
<!– 事务管理:JDBC原生事务 –>
<transactionManager type="JDBC"></transactionManager>
<!– 数据源:连接池 –>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis?useSSL=false&amp;serverTimezone=Asia/Shanghai&amp;characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="1111"/>
</dataSource>
</environment>
</environments>
<!– 加载Mapper映射文件 –>
<mappers>
<mapper resource="com/hg/dao/UserMapper.xml"/>
</mappers>
</configuration>

2.3 测试代码

public class MyBatisTest {

private InputStream inputStream;
private SqlSession sqlSession;

@Before
public void createSqlSession() throws IOException {
// 1.加载配置文件
String resource = "mybatis-config.xml";
inputStream = Resources.getResourceAsStream(resource);

// 2.创建SqlSessionFactory
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

// 3.获取SqlSession
sqlSession = sqlSessionFactory.openSession();
}

@Test
public void testFindAll(){
// 4.获取Mapper代理对象
UserDao userDao = sqlSession.getMapper(UserMapper.class);

// 5.执行查询
List<User> userList = userMapper.findAll();

// 6.输出结果
for(User user : userList) {
System.out.println(user);
}
}

@After
public void closeSqlSession() throws IOException {
// 7.释放资源
sqlSession.close();
inputStream.close();
}
}

2.4 MyBatis 运行原理

MyBatis 执行流程核心 8 步:

  • 读取全局配置文件(mybatis-config.xml)
  • 加载 Mapper 映射文件(SQL 配置)
  • 构建 SqlSessionFactory(会话工厂)
  • 创建 SqlSession(数据库会话)
  • 通过 Executor 执行器处理 SQL
  • 封装 MappedStatement(SQL + 参数 + 返回值)
  • 输入参数映射(替换 SQL 占位符)
  • 输出结果映射(封装为 Java 对象)
  • 三、MyBatis 核心 CRUD 操作

    3.1 查询操作

    (1)单个参数查询

    // DAO接口
    public User findUserById(Integer id);

    <!– Mapper配置 –>
    <select id="findUserById" parameterType="java.lang.Integer" resultType="com.hg.pojo.User">
    select * from user where id=#{id}
    </select>

    (2)多参数查询
    方式 1:序号绑定

    public User findUserByIdAndName(Integer id, String username);

    <select id="findUserByIdAndName" resultType="com.hg.pojo.User">
    SELECT * FROM user WHERE id = #{arg0} AND username = #{arg1}
    <!– 或使用param1/param2:WHERE id = #{param1} AND username = #{param2} –>
    </select>

    方式 2:注解绑定

    public User findUserByIdAndName2(@Param("id") Integer id, @Param("username")String username);

    <select id="findUserByIdAndName2" resultType="com.hg.pojo.User">
    SELECT * FROM user WHERE id = #{id} AND username = #{username}
    </select>

    方式 3:对象绑定

    public User findUserByUserInfo(User user);

    <select id="findUserByUserInfo" parameterType="com.hg.pojo.User" resultType="com.hg.pojo.User">
    SELECT * FROM user WHERE id = #{id} AND username = #{username}
    </select>

    方式 4:Map 绑定

    public User findUserByMap(Map<String, Object> map);

    <select id="findUserByMap" parameterMap="java.util.Map" resultType="com.hg.pojo.User">
    SELECT * FROM user WHERE id = #{id} AND username = #{username}
    </select>

    (3)模糊查询

    public List<User> findUserByName(String username);

    <select id="findUserByName" parameterType="string" resultType="com.hg.pojo.User">
    <!– 推荐方式:防止SQL注入 –>
    select * from user where username like concat('%',#{username},'%')
    <!– 或:select * from user where username like '%${value}%' –>
    </select>

    (4)聚合函数查询

    public Integer getTotal();

    <select id="getTotal" resultType="int">
    SELECT COUNT(id) FROM user
    </select>

    3.2 删除操作

    public void deleteUserById(Integer id);

    <delete id="deleteUserById" parameterType="Integer">
    DELETE FROM user WHERE id = #{id}
    </delete>

    // 测试代码
    @Test
    public void testDeleteUserById(){
    UserDao userDao = sqlSession.getMapper(UserDao.class);
    userDao.deleteUserById(41);
    sqlSession.commit(); // 手动提交事务
    }

    3.3 修改操作

    public void updateUserById(User user);

    <update id="updateUserById" parameterType="com.hg.pojo.User">
    update user set username=#{username},password=#{password},
    birthday=#{birthday},sex=#{sex},address=#{address} where id=#{id}
    </update>

    @Test
    public void testUpdateUserById(){
    User userParam = new User();
    userParam.setId(41);
    userParam.setUsername("吴彦祖");
    userParam.setSex("男");
    userParam.setAddress("中国");
    userParam.setBirthday(new Date());
    userMapper.updateUserById(userParam);
    }

    3.4 新增操作(含主键回填)

    public void insertUser(User user);

    <insert id="insertUser" useGeneratedKeys="true" keyProperty="id" parameterType="com.hg.pojo.User">
    insert into user(username,password,birthday,sex,address)
    values(#{username},#{password},#{birthday},#{sex},#{address})
    </insert>

    @Test
    public void testInsertUser(){
    UserDao userDao = sqlSession.getMapper(UserDao.class);
    User user = new User();
    user.setUsername("刘德华");
    user.setPassword("111");
    user.setBirthday(new Date());
    user.setSex("男");
    user.setAddress("香港");
    userDao.insertUser(user);
    System.out.println("新增记录的id值:"+user.getId()); // 获取自增主键
    sqlSession.commit();
    }

    3.5 #{} vs ${} 核心区别

    特性#{}${}
    本质 预编译占位符 SQL 字符串拼接
    类型转换 自动 Java/JDBC 类型转换 无类型转换
    SQL 注入 可防止注入 存在注入风险
    参数绑定 支持任意参数名(单个参数可写 value) 单个参数只能写 value

    四、自定义 MyBatis(核心原理剖析)

    4.1 核心设计模式

    MyBatis 大量使用设计模式简化开发:

    • 构建者模式:SqlSessionFactoryBuilder(屏蔽对象构建细节)
    • 工厂模式:SqlSessionFactory(解耦 SqlSession 创建)
    • 代理模式:SqlSession(创建 Mapper 代理对象)

    4.2 核心对象封装

    (1)配置类(Configuration)

    public class Configuration {
    private String driver;
    private String url;
    private String username;
    private String password;
    // 存储Mapper配置:key=namespace+id
    private Map<String, MappedStatement> mappers = new HashMap<>();

    // Getter & Setter
    }

    (2)SQL 封装类(MappedStatement)

    public class MappedStatement {
    private String queryString; // SQL语句
    private String resultType; // 返回值类型

    // Getter & Setter
    }

    (3)核心工具类
    • Resources:加载配置文件
    • XMLConfigBuilder:解析 XML 配置
    • DataSourceUtil:获取数据库连接
    • Executor:执行 SQL 并封装结果

    五、原始 DAO 开发(了解)

    5.1 DAO 实现类

    public class UserDaoImpl implements UserDao {
    private SqlSession sqlSession;

    public UserDaoImpl(SqlSession sqlSession) {
    this.sqlSession = sqlSession;
    }

    @Override
    public List<User> findAll() {
    return sqlSession.selectList("com.hg.dao.UserDao.findAll");
    }

    @Override
    public User findUserById(Integer id) {
    return sqlSession.selectOne("com.hg.dao.UserDao.findUserById", id);
    }

    // 其他CRUD方法实现…
    }

    5.2 原始 DAO vs 代理 DAO 对比

    特性原始 DAO代理 DAO
    代码量 需手动实现 DAO 类 仅需接口 + Mapper,自动生成代理
    维护成本 高(SQL 与代码耦合) 低(SQL 集中配置)
    开发效率
    主流程度 几乎淘汰 目前主流

    六、总结

    MyBatis 作为轻量级持久层框架,核心优势在于:

  • 简化 JDBC 操作,专注 SQL 开发
  • 灵活的 SQL 配置,支持动态 SQL / 关联查询
  • 低侵入性,与 Spring 等框架无缝整合
  • 强大的结果映射,支持复杂对象封装
  • 掌握 MyBatis 核心原理,不仅能熟练使用框架,更能理解其设计思想,为解决复杂业务场景打下基础。


    如果本文对你有帮助,记得收藏、点赞、关注~~~

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » MyBatis 从入门到精通
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!