MyBatis 从入门到精通:详解基础与实战(完整版)


MyBatis 从入门到精通:详解基础与实战(完整版)

(新手入门篇在主页)


一、MyBatis 基础概念
1.1 什么是 ORM?

ORM(Object-Relational Mapping)即对象关系映射,是一种将数据库表与程序对象自动映射的技术。MyBatis 作为半自动化的 ORM 框架,允许开发者直接编写 SQL,同时自动处理对象与数据库结果的映射。

1.2 MyBatis 核心功能
  • SQL 映射:将 Java 方法与 SQL 语句绑定
  • 动态 SQL:根据条件动态拼接 SQL
  • 事务管理:支持声明式和编程式事务
  • 缓存机制:提供一级缓存和二级缓存
1.3 核心组件
组件 说明
SqlSessionFactory 全局单例,用于创建 SqlSession(类似数据库连接池)
SqlSession 线程非安全的会话对象,用于执行 SQL 和获取映射器
Executor SQL 执行器,包含 Simple、Reuse、Batch 三种模式
MapperProxy 动态代理对象,将接口方法调用转换为 SQL 执行

二、环境搭建与配置
2.1 使用 IDEA 创建 Maven 项目
  1. 新建项目
    File → New → Project → Maven → 选择 JDK 版本

  2. 配置目录结构

    src
    ├── main
    │   ├── java
    │   │   └── com
    │   │       └── example
    │   │           ├── entity    # 实体类
    │   │           ├── dao       # Mapper 接口
    │   │           └── utils     # 工具类
    │   ├── resources
    │   │   ├── mybatis-config.xml  # 主配置文件
    │   │   └── mapper/*.xml        # Mapper XML
    │   └── webapp
    │       └── WEB-INF
    └── test
        └── java                  # 测试代码
    
2.2 添加 Maven 依赖

<dependencies>
    
    <dependency>
        <groupId>org.mybatisgroupId>
        <artifactId>mybatisartifactId>
        <version>3.5.13version>
    dependency>
    
    
    <dependency>
        <groupId>mysqlgroupId>
        <artifactId>mysql-connector-javaartifactId>
        <version>8.0.33version>
    dependency>
    
    
    <dependency>
        <groupId>org.slf4jgroupId>
        <artifactId>slf4j-apiartifactId>
        <version>1.7.36version>
    dependency>
dependencies>
2.3 配置数据库连接
  1. 创建数据库(Navicat 操作):

    CREATE DATABASE mybatis_demo 
      DEFAULT CHARACTER SET utf8mb4 
      COLLATE utf8mb4_0900_ai_ci;
      
    USE mybatis_demo;
    
    CREATE TABLE user (
      id INT PRIMARY KEY AUTO_INCREMENT,
      name VARCHAR(50) NOT NULL,
      age INT
    );
    
  2. 配置 mybatis-config.xml

    
    DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" 
    "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
        <environments default="development">
            <environment id="development">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                    <property name="url" value="jdbc:mysql://localhost:3306/mybatis_demo?useSSL=false"/>
                    <property name="username" value="root"/>
                    <property name="password" value="123456"/>
                dataSource>
            environment>
        environments>
        <mappers>
            <mapper resource="mapper/UserMapper.xml"/>
        mappers>
    configuration>
    

三、基础 CRUD 操作
3.1 实体类定义
package com.example.entity;

public class User {
    private Integer id;
    private String name;
    private Integer age;
    
    // Getter & Setter 省略
}
3.2 Mapper 接口
package com.example.dao;

public interface UserMapper {
    // 插入用户
    int insert(User user);
    
    // 根据 ID 查询
    User selectById(Integer id);
    
    // 更新年龄
    int updateAge(@Param("id") Integer id, @Param("age") Integer age);
    
    // 删除用户
    int delete(Integer id);
}
3.3 XML 映射文件

<mapper namespace="com.example.dao.UserMapper">
    
    <insert id="insert" parameterType="User" useGeneratedKeys="true" keyProperty="id">
        INSERT INTO user(name, age) 
        VALUES(#{name}, #{age})
    insert>
    
    <select id="selectById" resultType="User">
        SELECT * FROM user WHERE id = #{id}
    select>
    
    <update id="updateAge">
        UPDATE user SET age = #{age} WHERE id = #{id}
    update>
    
    <delete id="delete">
        DELETE FROM user WHERE id = #{id}
    delete>
mapper>
3.4 工具类封装
package com.example.utils;

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 java.io.IOException;
import java.io.InputStream;

public class MyBatisUtil {
    private static SqlSessionFactory sqlSessionFactory;
    
    static {
        try {
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            throw new RuntimeException("初始化 MyBatis 失败", e);
        }
    }
    
    public static SqlSession getSqlSession() {
        return sqlSessionFactory.openSession();
    }
}
3.5 测试用例
public class UserMapperTest {
    @Test
    public void testCRUD() {
        try (SqlSession session = MyBatisUtil.getSqlSession()) {
            UserMapper mapper = session.getMapper(UserMapper.class);
            
            // 插入
            User user = new User();
            user.setName("张三");
            user.setAge(25);
            mapper.insert(user);
            System.out.println("插入ID: " + user.getId());
            
            // 查询
            User dbUser = mapper.selectById(user.getId());
            System.out.println("查询结果: " + dbUser);
            
            // 更新
            mapper.updateAge(user.getId(), 30);
            
            // 删除
            mapper.delete(user.getId());
            
            session.commit();
        }
    }
}

四、动态 SQL 详解
4.1 常用动态标签
标签 作用 示例
条件判断
多条件选择(类似 switch-case) 包含
智能去除多余关键字 替代 处理复杂条件
遍历集合 用于 IN 查询
4.2 复杂查询示例
<select id="selectByCondition" parameterType="map" resultType="User">
    SELECT * FROM user
    <where>
        <if test="name != null and name != ''">
            AND name LIKE CONCAT('%', #{name}, '%')
        if>
        <if test="minAge != null">
            AND age >= #{minAge}
        if>
        <if test="maxAge != null">
            AND age <= #{maxAge}
        if>
    where>
    ORDER BY id DESC
select>
4.3 批量插入数据
<insert id="batchInsert" parameterType="list">
    INSERT INTO user(name, age) VALUES
    <foreach collection="list" item="user" separator=",">
        (#{user.name}, #{user.age})
    foreach>
insert>

五、结果映射与高级查询
5.1 复杂结果映射

<resultMap id="userResultMap" type="User">
    <id property="id" column="user_id"/>
    <result property="name" column="user_name"/>
    <result property="age" column="user_age"/>
resultMap>

<select id="selectComplex" resultMap="userResultMap">
    SELECT 
        id AS user_id,
        name AS user_name,
        age AS user_age
    FROM user
select>
5.2 关联查询(一对多)
<resultMap id="userWithOrders" type="User">
    <id property="id" column="id"/>
    <result property="name" column="name"/>
    <collection property="orders" ofType="Order">
        <id property="orderId" column="order_id"/>
        <result property="orderNo" column="order_no"/>
    collection>
resultMap>

<select id="selectUserWithOrders" resultMap="userWithOrders">
    SELECT 
        u.*, 
        o.id AS order_id,
        o.no AS order_no
    FROM user u
    LEFT JOIN orders o ON u.id = o.user_id
    WHERE u.id = #{id}
select>

六、事务管理与缓存
6.1 事务控制方式
try (SqlSession session = sqlSessionFactory.openSession()) {
    try {
        UserMapper mapper = session.getMapper(UserMapper.class);
        // 业务操作
        session.commit();
    } catch (Exception e) {
        session.rollback();
    }
}
6.2 缓存配置
  1. 一级缓存

    • 默认开启,Session 级别
    • 在同一个 SqlSession 中有效
  2. 二级缓存

    • 需在 mapper.xml 中启用:

      <cache eviction="LRU" flushInterval="60000" size="1024"/>
      
    • 实体类需实现 Serializable 接口


七、整合 JavaWeb 项目
7.1 在 Servlet 中使用 MyBatis
@WebServlet("/user")
public class UserServlet extends HttpServlet {
    private UserMapper userMapper;
    
    @Override
    public void init() {
        SqlSession session = MyBatisUtil.getSqlSession();
        userMapper = session.getMapper(UserMapper.class);
    }
    
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
        List<User> users = userMapper.selectAll();
        // 将数据传递到 JSP
        req.setAttribute("users", users);
        req.getRequestDispatcher("/userList.jsp").forward(req, resp);
    }
}
7.2 JSP 页面展示
<%@ page contentType="text/html;charset=UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>


    用户列表


    
            
ID 姓名 年龄
${user.id} ${user.name} ${user.age}

八、常见问题与解决方案
8.1 配置文件未加载

现象Invalid bound statement (not found)
解决

  1. 检查 XML 文件是否在 resources/mapper 目录

  2. 确认 mybatis-config.xml 中 路径正确

  3. Maven 添加资源过滤:

    <build>
        <resources>
            <resource>
                <directory>src/main/resourcesdirectory>
                <includes>
                    <include>**/*.xmlinclude>
                includes>
            resource>
        resources>
    build>
    
8.2 中文乱码问题

解决

  1. 数据库连接 URL 添加参数:

    jdbc:mysql://localhost:3306/db?useUnicode=true&characterEncoding=utf8
    
  2. 确保 JSP 页面设置编码:

    <%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"%>
    

九、扩展:整合 Redis 缓存
9.1 添加 Redis 依赖
<dependency>
    <groupId>redis.clientsgroupId>
    <artifactId>jedisartifactId>
    <version>4.4.6version>
dependency>
9.2 实现 Redis 缓存
public class RedisCache implements Cache {
    private final String id;
    private static JedisPool jedisPool;

    public RedisCache(String id) {
        this.id = id;
    }

    @Override
    public String getId() {
        return id;
    }

    @Override
    public void putObject(Object key, Object value) {
        try (Jedis jedis = jedisPool.getResource()) {
            jedis.hset(id, key.toString(), SerializeUtil.serialize(value));
        }
    }

    @Override
    public Object getObject(Object key) {
        try (Jedis jedis = jedisPool.getResource()) {
            return SerializeUtil.unserialize(jedis.hget(id, key.toString()));
        }
    }
}

**十、总结

MyBatis 以配置化与动态代理为核心,通过解耦 SQL 与代码、自动化结果映射及灵活的动态 SQL 标签,将 JDBC 的繁琐操作转化为简洁的接口方法。其分层架构(接口层、核心处理层、基础支持层)结合 XML/注解配置,既保留了原生 SQL 的灵活性,又通过批处理、分页优化与二级缓存机制提升了性能,同时依托插件体系与 Spring 集成实现事务管理和扩展定制,最终在简化开发、保障安全性与维护性之间取得了优雅平衡,成为 Java 持久层的高效解决方案。


通过本文的系统学习,您已掌握 MyBatis 的核心用法与进阶技巧。建议从简单项目入手,逐步实践复杂场景,最终达到精通水平。

你可能感兴趣的:(mybatis)