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

相关文章
|
10天前
|
XML 监控 Java
Spring学习知识点大全(三)
教程来源 https://app-aakcgtuh1ywx.appmiaoda.com 本文系统介绍Spring生态核心实践:涵盖单元测试(MockBean+断言)、集成测试(MockMvc+事务回滚)、SpEL表达式(属性注入、集合操作等)、Spring Boot自动配置原理及YAML配置要点,助力高效构建企业级应用。
|
传感器 消息中间件 运维
Mqtt开发笔记:Mqtt服务器搭建
Mqtt开发笔记:Mqtt服务器搭建
Mqtt开发笔记:Mqtt服务器搭建
|
SQL Oracle 关系型数据库
【Oracle】玩转Oracle数据库(三):数据库的创建和管理
【Oracle】玩转Oracle数据库(三):数据库的创建和管理
429 5
|
应用服务中间件 nginx
Nginx rewrite(URL)地址重定向
Nginx rewrite(URL)地址重定向
1084 0
|
11月前
|
安全 JavaScript 前端开发
HarmonyOS NEXT~HarmonyOS 语言仓颉:下一代分布式开发语言的技术解析与应用实践
HarmonyOS语言仓颉是华为专为HarmonyOS生态系统设计的新型编程语言,旨在解决分布式环境下的开发挑战。它以“编码创造”为理念,具备分布式原生、高性能与高效率、安全可靠三大核心特性。仓颉语言通过内置分布式能力简化跨设备开发,提供统一的编程模型和开发体验。文章从语言基础、关键特性、开发实践及未来展望四个方面剖析其技术优势,助力开发者掌握这一新兴工具,构建全场景分布式应用。
962 35
|
9月前
|
SQL XML Java
MyBatis Mapper中使用limit参数的查询问题
总结而言,MyBatis中使用 `limit`参数的查询可以高度定制并且灵活,基于方法签名和XML映射文件的组合来达成多样化的查询需求。通过参数化查询和动态SQL,MyBatis可以有效地处理各种复杂情境下的数据库操作,并且将SQL语句的维护与业务代码的编写相分离,提升代码的可维护性和可阅读性。
740 13
|
8月前
|
人工智能 JSON 编译器
Code和Clang配置C++开发环境
本文介绍了如何在VS Code中配置C++开发环境,包括安装VS Code、C++扩展、Clang编译器,创建并运行Hello World项目,使用IntelliSense、调试程序及自定义配置等内容,帮助开发者快速上手C++开发。
925 0
|
JavaScript 前端开发 Java
建立SpringBoot项目
在最新版本中,通过Eclipse建立Spring Boot项目,使用在Eclipse市场安装目前不太稳定,需要重新安装Spring Boot版本的Eclipse,现在介绍如何进行。
1615 0
建立SpringBoot项目
|
前端开发 JavaScript UED
什么是 CSS Modules ?我们为什么需要它们
CSS Modules 是一种将 CSS 与模块系统结合的技术,通过局部作用域和模块隔离,解决了传统 CSS 全局样式污染的问题。本文介绍了 CSS Modules 的基本概念、主要特点及其优势,包括自动生成唯一类名、提高代码可维护性和可读性、支持动态样式和主题切换等,并提供了 React 中的使用示例。
771 6