MyBatis学习知识点大全(一)

简介: 教程来源 https://app-abggx9rbr6dd.appmiaoda.com MyBatis 是轻量级Java持久层框架,简化JDBC开发,支持XML/注解映射、动态SQL、缓存及Spring集成。本文系统梳理其核心概念、架构原理、环境搭建与动态SQL等关键知识点,助力初学者构建完整知识体系,也为开发者提供深度技术参考。

MyBatis 作为一款优秀的持久层框架,凭借其灵活的 SQL 映射、强大的动态 SQL 能力、轻量级的架构设计,在企业级 Java 应用中占据重要地位。它消除了几乎所有的 JDBC 代码和参数的手工设置以及结果集的检索,通过简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs 映射成数据库中的记录。本文将系统全面地梳理 MyBatis 的核心知识点,从基础概念到高级特性,帮助初学者建立完整的知识体系,也为有经验的开发者提供深入的技术参考。
eb407f35-acac-4885-942b-aac0be2a456b.png

一、MyBatis 概述

1.1 什么是 MyBatis
MyBatis 是一款优秀的持久层框架,支持自定义 SQL、存储过程以及高级映射。它通过 XML 或注解的方式,将 Java 对象与 SQL 语句进行映射,简化了 JDBC 编程的复杂性。

核心特性:
消除 JDBC 冗余代码,简化持久层开发
支持动态 SQL,灵活构建查询条件
提供强大的映射器,支持复杂对象关系映射
支持与 Spring 等框架无缝集成
支持缓存机制,提升查询性能
支持存储过程调用
轻量级,学习成本低

1.2 架构原理

MyBatis 架构层次:
┌─────────────────────────────────────────┐
│           Interface Layer                │
│     (SqlSession, Mapper Interface)       │
├─────────────────────────────────────────┤
│           Data Processing Layer          │
│   (Parameter Mapping, SQL Execution)     │
├─────────────────────────────────────────┤
│           SQL Mapping Layer              │
│     (XML Mapping, Annotation Mapping)    │
├─────────────────────────────────────────┤
│           Base Support Layer             │
│   (Transaction, Cache, Connection)       │
└─────────────────────────────────────────┘

工作流程:

读取配置文件(mybatis-config.xml)

创建 SqlSessionFactory

通过 SqlSessionFactory 创建 SqlSession

通过 SqlSession 获取 Mapper 代理对象

执行 Mapper 方法,执行 SQL

返回结果映射到 Java 对象

1.3 环境搭建
Maven 依赖:

<dependencies>
    <!-- MyBatis 核心依赖 -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.13</version>
    </dependency>

    <!-- 数据库驱动 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.33</version>
    </dependency>

    <!-- 日志 -->
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.4.11</version>
    </dependency>
</dependencies>

核心配置文件 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>
    <!-- 配置属性 -->
    <properties resource="jdbc.properties"/>

    <!-- 配置全局设置 -->
    <settings>
        <!-- 开启驼峰命名转换 -->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <!-- 开启延迟加载 -->
        <setting name="lazyLoadingEnabled" value="true"/>
        <!-- 开启二级缓存 -->
        <setting name="cacheEnabled" value="true"/>
        <!-- 日志实现 -->
        <setting name="logImpl" value="SLF4J"/>
    </settings>

    <!-- 类型别名 -->
    <typeAliases>
        <package name="com.example.entity"/>
    </typeAliases>

    <!-- 环境配置 -->
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>

    <!-- 映射器配置 -->
    <mappers>
        <package name="com.example.mapper"/>
    </mappers>
</configuration>

jdbc.properties:

driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis_demo?useSSL=false&serverTimezone=UTC
username=root
password=123456

初始化 SqlSessionFactory:

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.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 (Exception e) {
            e.printStackTrace();
        }
    }

    public static SqlSession getSqlSession() {
        return sqlSessionFactory.openSession();
    }

    public static SqlSession getSqlSession(boolean autoCommit) {
        return sqlSessionFactory.openSession(autoCommit);
    }
}

二、核心组件

2.1 SqlSessionFactory 与 SqlSession

public class SqlSessionDemo {

    // SqlSessionFactory 是线程安全的,应该作为单例
    private SqlSessionFactory sqlSessionFactory;

    // 获取 SqlSession
    public void testSqlSession() {
        // 默认不自动提交
        try (SqlSession session = sqlSessionFactory.openSession()) {
            // 执行操作
            UserMapper mapper = session.getMapper(UserMapper.class);
            User user = mapper.selectById(1L);
            System.out.println(user);

            // 手动提交
            session.commit();
        } catch (Exception e) {
            // 回滚
            session.rollback();
        }

        // 自动提交事务
        try (SqlSession session = sqlSessionFactory.openSession(true)) {
            UserMapper mapper = session.getMapper(UserMapper.class);
            mapper.insert(new User("张三", 25));
        }

        // 设置执行器类型
        try (SqlSession session = sqlSessionFactory.openSession(
                ExecutorType.BATCH)) {  // SIMPLE, REUSE, BATCH
            UserMapper mapper = session.getMapper(UserMapper.class);
            // 批量操作
            for (int i = 0; i < 1000; i++) {
                mapper.insert(new User("user" + i, i));
            }
            session.commit();
        }
    }
}

2.2 Mapper 接口与 XML 映射
实体类:

package com.example.entity;

import java.io.Serializable;
import java.util.Date;

public class User implements Serializable {
    private Long id;
    private String username;
    private String password;
    private Integer age;
    private String email;
    private Date createTime;
    private Date updateTime;

    // 构造函数、getter、setter
    public User() {}

    public User(String username, Integer age) {
        this.username = username;
        this.age = age;
    }

    // getter/setter 省略
}

Mapper 接口:

package com.example.mapper;

import com.example.entity.User;
import org.apache.ibatis.annotations.*;
import java.util.List;
import java.util.Map;

public interface UserMapper {

    // 基本 CRUD 方法
    User selectById(@Param("id") Long id);

    List<User> selectAll();

    int insert(User user);

    int update(User user);

    int deleteById(Long id);

    // 多条件查询
    List<User> selectByCondition(@Param("username") String username, 
                                  @Param("age") Integer age);

    // 使用 Map 参数
    List<User> selectByMap(Map<String, Object> params);

    // 返回 Map
    Map<String, Object> selectMapById(Long id);

    // 分页查询
    List<User> selectByPage(@Param("offset") int offset, 
                             @Param("limit") int limit);

    // 批量插入
    int batchInsert(@Param("list") List<User> users);
}

XML 映射文件 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">
<mapper namespace="com.example.mapper.UserMapper">

    <!-- 结果映射 -->
    <resultMap id="userResultMap" type="com.example.entity.User">
        <id property="id" column="id" jdbcType="BIGINT"/>
        <result property="username" column="username" jdbcType="VARCHAR"/>
        <result property="password" column="password" jdbcType="VARCHAR"/>
        <result property="age" column="age" jdbcType="INTEGER"/>
        <result property="email" column="email" jdbcType="VARCHAR"/>
        <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
        <result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
    </resultMap>

    <!-- 基础字段列表 -->
    <sql id="baseColumns">
        id, username, password, age, email, create_time, update_time
    </sql>

    <!-- 根据ID查询 -->
    <select id="selectById" resultMap="userResultMap" parameterType="long">
        SELECT <include refid="baseColumns"/>
        FROM user
        WHERE id = #{id}
    </select>

    <!-- 查询所有 -->
    <select id="selectAll" resultType="com.example.entity.User">
        SELECT <include refid="baseColumns"/>
        FROM user
        ORDER BY id DESC
    </select>

    <!-- 插入用户 -->
    <insert id="insert" parameterType="com.example.entity.User" 
            useGeneratedKeys="true" keyProperty="id">
        INSERT INTO user (username, password, age, email, create_time, update_time)
        VALUES (#{username}, #{password}, #{age}, #{email}, 
                NOW(), NOW())
    </insert>

    <!-- 更新用户 -->
    <update id="update" parameterType="com.example.entity.User">
        UPDATE user
        SET username = #{username},
            password = #{password},
            age = #{age},
            email = #{email},
            update_time = NOW()
        WHERE id = #{id}
    </update>

    <!-- 删除用户 -->
    <delete id="deleteById" parameterType="long">
        DELETE FROM user WHERE id = #{id}
    </delete>

    <!-- 条件查询 -->
    <select id="selectByCondition" resultMap="userResultMap">
        SELECT <include refid="baseColumns"/>
        FROM user
        WHERE 1 = 1
        <if test="username != null and username != ''">
            AND username LIKE CONCAT('%', #{username}, '%')
        </if>
        <if test="age != null">
            AND age = #{age}
        </if>
    </select>

    <!-- Map参数查询 -->
    <select id="selectByMap" resultMap="userResultMap" parameterType="map">
        SELECT <include refid="baseColumns"/>
        FROM user
        WHERE 1 = 1
        <if test="username != null">
            AND username = #{username}
        </if>
        <if test="minAge != null">
            AND age >= #{minAge}
        </if>
        <if test="maxAge != null">
            AND age &lt;= #{maxAge}
        </if>
    </select>

    <!-- 返回Map -->
    <select id="selectMapById" resultType="map" parameterType="long">
        SELECT <include refid="baseColumns"/>
        FROM user
        WHERE id = #{id}
    </select>

    <!-- 分页查询 -->
    <select id="selectByPage" resultMap="userResultMap">
        SELECT <include refid="baseColumns"/>
        FROM user
        ORDER BY id DESC
        LIMIT #{offset}, #{limit}
    </select>

    <!-- 批量插入 -->
    <insert id="batchInsert" parameterType="list">
        INSERT INTO user (username, age, create_time, update_time)
        VALUES
        <foreach collection="list" item="user" separator=",">
            (#{user.username}, #{user.age}, NOW(), NOW())
        </foreach>
    </insert>
</mapper>

三、动态 SQL

3.1 if 标签

<!-- if 条件判断 -->
<select id="findUsers" resultType="User">
    SELECT * FROM user
    WHERE 1 = 1
    <if test="username != null and username != ''">
        AND username LIKE CONCAT('%', #{username}, '%')
    </if>
    <if test="age != null">
        AND age = #{age}
    </if>
    <if test="minAge != null">
        AND age >= #{minAge}
    </if>
    <if test="maxAge != null">
        AND age &lt;= #{maxAge}
    </if>
</select>

<!-- 更优雅的写法,避免 WHERE 1=1 -->
<select id="findUsers" resultType="User">
    SELECT * FROM user
    <where>
        <if test="username != null and username != ''">
            username LIKE CONCAT('%', #{username}, '%')
        </if>
        <if test="age != null">
            AND age = #{age}
        </if>
        <if test="minAge != null">
            AND age >= #{minAge}
        </if>
        <if test="maxAge != null">
            AND age &lt;= #{maxAge}
        </if>
    </where>
</select>

3.2 choose/when/otherwise 标签

<!-- choose 相当于 switch-case -->
<select id="findUsersByChoice" resultType="User">
    SELECT * FROM user
    <where>
        <choose>
            <when test="username != null and username != ''">
                username LIKE CONCAT('%', #{username}, '%')
            </when>
            <when test="age != null">
                age = #{age}
            </when>
            <otherwise>
                status = 1
            </otherwise>
        </choose>
    </where>
</select>

3.3 where 标签

<!-- where 标签会自动处理 AND/OR 前缀 -->
<select id="findUsers" resultType="User">
    SELECT * FROM user
    <where>
        <if test="username != null">
            AND username LIKE CONCAT('%', #{username}, '%')
        </if>
        <if test="age != null">
            AND age = #{age}
        </if>
        <if test="email != null">
            AND email = #{email}
        </if>
    </where>
</select>

3.4 set 标签

<!-- set 标签用于动态更新语句 -->
<update id="updateUser" parameterType="User">
    UPDATE user
    <set>
        <if test="username != null">username = #{username},</if>
        <if test="password != null">password = #{password},</if>
        <if test="age != null">age = #{age},</if>
        <if test="email != null">email = #{email},</if>
        update_time = NOW()
    </set>
    WHERE id = #{id}
</update>

3.5 foreach 标签

<!-- 遍历集合 -->
<select id="selectByIds" resultType="User">
    SELECT * FROM user
    WHERE id IN
    <foreach collection="ids" item="id" open="(" separator="," close=")">
        #{id}
    </foreach>
</select>

<!-- 批量插入 -->
<insert id="batchInsert">
    INSERT INTO user (username, age, create_time)
    VALUES
    <foreach collection="list" item="user" separator=",">
        (#{user.username}, #{user.age}, NOW())
    </foreach>
</insert>

<!-- 批量更新 -->
<update id="batchUpdate">
    <foreach collection="list" item="user" separator=";">
        UPDATE user
        SET username = #{user.username},
            age = #{user.age}
        WHERE id = #{user.id}
    </foreach>
</update>

<!-- 遍历 Map 参数 -->
<select id="selectByMap" resultType="User">
    SELECT * FROM user
    WHERE 1 = 1
    <foreach collection="params" index="key" item="value">
        <if test="key == 'username'">
            AND username = #{value}
        </if>
        <if test="key == 'age'">
            AND age = #{value}
        </if>
    </foreach>
</select>

3.6 trim 标签

<!-- trim 标签可以自定义前缀、后缀和去除的字符 -->
<select id="findUsers" resultType="User">
    SELECT * FROM user
    <trim prefix="WHERE" prefixOverrides="AND |OR ">
        <if test="username != null">
            AND username LIKE CONCAT('%', #{username}, '%')
        </if>
        <if test="age != null">
            AND age = #{age}
        </if>
        <if test="email != null">
            AND email = #{email}
        </if>
    </trim>
</select>

<!-- trim 用于更新 -->
<update id="updateUser">
    UPDATE user
    <trim prefix="SET" suffixOverrides=",">
        <if test="username != null">username = #{username},</if>
        <if test="password != null">password = #{password},</if>
        <if test="age != null">age = #{age},</if>
        <if test="email != null">email = #{email},</if>
        update_time = NOW(),
    </trim>
    WHERE id = #{id}
</update>

3.7 bind 标签

<!-- bind 用于创建绑定变量 -->
<select id="findUsers" resultType="User">
    <bind name="pattern" value="'%' + username + '%'"/>
    SELECT * FROM user
    WHERE username LIKE #{pattern}
</select>

<!-- 复杂绑定 -->
<select id="findUsers" resultType="User">
    <bind name="start" value="(page - 1) * size"/>
    <bind name="end" value="page * size"/>
    SELECT * FROM user
    ORDER BY id DESC
    LIMIT #{start}, #{size}
</select>

3.8 sql 与 include

<!-- 定义可重用的 SQL 片段 -->
<sql id="userColumns">
    id, username, password, age, email, create_time, update_time
</sql>

<sql id="userWhere">
    <where>
        <if test="username != null">
            AND username LIKE CONCAT('%', #{username}, '%')
        </if>
        <if test="age != null">
            AND age = #{age}
        </if>
    </where>
</sql>

<!-- 引用 SQL 片段 -->
<select id="selectUsers" resultType="User">
    SELECT <include refid="userColumns"/>
    FROM user
    <include refid="userWhere"/>
</select>

<!-- 带参数的 SQL 片段 -->
<sql id="userColumnsWithAlias">
    ${alias}.id, ${alias}.username, ${alias}.age
</sql>

<select id="selectUsersWithAlias" resultType="User">
    SELECT <include refid="userColumnsWithAlias">
        <property name="alias" value="u"/>
    </include>
    FROM user u
</select>

来源:
https://app-abggx9rbr6dd.appmiaoda.com

相关文章
|
4天前
|
人工智能 JSON 机器人
让龙虾成为你的“公众号分身” | 阿里云服务器玩Openclaw
本文带你零成本玩转OpenClaw:学生认证白嫖6个月阿里云服务器,手把手配置飞书机器人、接入免费/高性价比AI模型(NVIDIA/通义),并打造微信公众号“全自动分身”——实时抓热榜、AI选题拆解、一键发布草稿,5分钟完成热点→文章全流程!
10568 53
让龙虾成为你的“公众号分身” | 阿里云服务器玩Openclaw
|
9天前
|
人工智能 JavaScript API
解放双手!OpenClaw Agent Browser全攻略(阿里云+本地部署+免费API+网页自动化场景落地)
“让AI聊聊天、写代码不难,难的是让它自己打开网页、填表单、查数据”——2026年,无数OpenClaw用户被这个痛点困扰。参考文章直击核心:当AI只能“纸上谈兵”,无法实际操控浏览器,就永远成不了真正的“数字员工”。而Agent Browser技能的出现,彻底打破了这一壁垒——它给OpenClaw装上“上网的手和眼睛”,让AI能像真人一样打开网页、点击按钮、填写表单、提取数据,24小时不间断完成网页自动化任务。
2393 5
|
23天前
|
人工智能 JavaScript Ubuntu
5分钟上手龙虾AI!OpenClaw部署(阿里云+本地)+ 免费多模型配置保姆级教程(MiniMax、Claude、阿里云百炼)
OpenClaw(昵称“龙虾AI”)作为2026年热门的开源个人AI助手,由PSPDFKit创始人Peter Steinberger开发,核心优势在于“真正执行任务”——不仅能聊天互动,还能自动处理邮件、管理日程、订机票、写代码等,且所有数据本地处理,隐私完全可控。它支持接入MiniMax、Claude、GPT等多类大模型,兼容微信、Telegram、飞书等主流聊天工具,搭配100+可扩展技能,成为兼顾实用性与隐私性的AI工具首选。
23996 121
|
3天前
|
人工智能 IDE API
2026年国内 Codex 安装教程和使用教程:GPT-5.4 完整指南
Codex已进化为AI编程智能体,不仅能补全代码,更能理解项目、自动重构、执行任务。本文详解国内安装、GPT-5.4接入、cc-switch中转配置及实战开发流程,助你从零掌握“描述需求→AI实现”的新一代工程范式。(239字)
2239 126

热门文章

最新文章