【吐血整理】MyBatis从入门到精通

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
简介: 本文介绍了 MyBatis 的使用指南,涵盖开发环境搭建、基础操作实例和进阶特性。首先,详细描述了 JDK 和 IDE 的安装及依赖引入,确保项目顺利运行。接着,通过创建用户表和实体类,演示了 CRUD 操作的全流程,包括查询、插入、更新和删除。最后,深入探讨了动态 SQL 和缓存机制等高级功能,帮助开发者提升数据库交互效率和代码灵活性。掌握这些内容,能显著提高 Java 编程中的数据库操作能力。

 目录

❤️二、开发环境搭建指南

💜(一)工具和依赖准备

💙(二)配置文件设置

💚三、基础操作实例详解

💛(一)表与实体类创建

❤️(二)CRUD 操作全流程

💛四、进阶特性探索

❤️(一)动态 SQL 魔法

💜(二)缓存机制揭秘

❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️

❤️❤️❤️

家人们,今天我可得跟你们唠唠我在 Java 编程学习里发现的一个超厉害的 “神器”——MyBatis。你们知道咱们写 Java 程序的时候,经常得跟数据库打交道,存数据、取数据,要是没有个趁手的工具,那可太费劲了。以前用传统的 JDBC 操作,写起代码来又长又啰嗦,还特别容易出错。这时候 MyBatis 就闪亮登场啦,它就像是咱们和数据库之间的一个超智能 “翻译官”,能把咱们 Java 代码里的操作指令,巧妙又高效地翻译成数据库能懂的语言,大大简化了数据库交互的流程,让咱们开发程序的效率蹭蹭往上涨,所以说,学好 MyBatis 对提升咱们的编程技能那可是相当重要!

❤️❤️❤️

❤️二、开发环境搭建指南

💛(一)工具和依赖准备

首先啊,咱们得把基础的工具准备好。JDK 那肯定是必不可少的啦,就好比咱们做饭得有锅,得安装一个合适的版本,建议至少是 JDK 8 及以上,这样才能保证后续运行顺畅。再就是 IDE,我推荐 IntelliJ IDEA,它就像是一个超豪华的编程厨房,各种功能一应俱全,用起来特别顺手。安装的时候,跟着安装向导一步一步来就行,没啥复杂的。


💛💛💛💛

有了工具,还得引入依赖。要是咱们用 Maven 来管理项目(就像找了个超细心的管家帮咱们打理项目需要的各种资源),就在项目的 pom.xml 文件里加上下面这些代码:

❤️❤️❤️❤️

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.10</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.28</version>
</dependency>

image.gif

这里的版本号你们可以去官网看看,有没有更新的,用最新的一般没啥问题。要是用 Gradle 管理项目,也类似,在 build.gradle 文件里这么写:

implementation 'org.mybatis:mybatis:3.5.10'
implementation 'mysql:mysql-connector-java:8.0.28'

image.gif

这就相当于告诉项目:“嘿,我要用 MyBatis 和 MySQL 数据库啦,你得把它们准备好。” 引入完依赖,咱们就迈出了成功的第一步。

❤️(二)配置文件设置

  1. 接下来讲讲 MyBatis 的核心配置文件,一般叫 mybatis-config.xml,这可是整个 MyBatis 运行的 “大脑中枢”。里面有几个关键要素,比如说数据源配置,这就像是告诉 MyBatis 数据库住在哪儿,用户名和密码是啥,才能连得上。要是连接 MySQL 数据库,代码大概是这样:💚💚💚💚💚
<dataSource type="POOLED">
    <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=UTC"/>
    <property name="username" value="root"/>
    <property name="password" value="123456"/>
</dataSource>

image.gif

注意啊,这里的 url 里的参数设置很重要,不同数据库驱动可能有不同要求,像 MySQL 8.0 就得加上时区设置,不然可能连不上或者报错。再就是环境切换,如果咱们开发、测试、生产环境用不同的数据库,就可以在配置文件里设置不同的环境,方便切换,就像换不同的衣服应对不同场合。还有别名设置,给一些常用的 Java 类在 MyBatis 里取个别名,后面写 SQL 映射的时候就方便多了,比如:

<typeAliases>
    <typeAlias alias="User" type="com.example.User"/>
</typeAliases>

image.gif

这就给咱们的 User 类取了个简单的别名 “User”,是不是很实用?

  1. 再说说 SQL 映射文件,这玩意也特别重要,它就像是 MyBatis 的 “翻译手册”,把咱们写的 Java 方法和 SQL 语句对应起来。一般起名有个规则,比如咱们有个 UserMapper 接口,对应的 SQL 映射文件就叫 UserMapper.xml,得放在合适的目录下,让 MyBatis 能找到,通常放在 resources 目录下的 mapper 文件夹里。然后要在核心配置文件里把它关联起来,像这样:
<mappers>
    <mapper resource="mapper/UserMapper.xml"/>
</mappers>

image.gif

在 SQL 映射文件里,咱们就可以写各种 SQL 语句啦,像查询用户信息:

<select id="getUserById" resultType="User">
    select * from users where id = #{id}
</select>

image.gif

这里的 id 就是对应 Java 方法的名字,resultType 是返回结果的类型,也就是咱们之前取别名的 User 类,这样 MyBatis 就能准确地把查询结果封装成咱们想要的 User 对象啦,是不是特别巧妙?

💜三、基础操作实例详解

❤️(一)表与实体类创建

咱们来实际操作一下,以一个简单的 “用户信息表” 为例,建表的 SQL 语句大概是这样:

CREATE TABLE users (
    id INT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50) NOT NULL,
    password VARCHAR(50) NOT NULL,
    email VARCHAR(100)
);

image.gif

这表有几个字段,ID 是主键,自动增长,用户名和密码不能为空,还有个邮箱字段。对应咱们得创建一个 Java 实体类,就叫 User:

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    private Integer id;
    private String username;
    private String password;
    private String email;
}

image.gif

这里我用了 Lombok 来简化代码,自动帮咱们生成 get、set、toString 等方法,这样代码看起来简洁多了。实体类的属性和表字段是一一对应的,这样 MyBatis 在做数据传输的时候,就能很方便地把表中的数据封装成 User 对象,或者把 User 对象的数据存到表里面,是不是很好理解?

❤️(二)CRUD 操作全流程

  1. 查询:在 Mapper.xml 中写查询语句,比如咱们要根据 ID 查询单个用户,代码刚才给大家看过了,再详细讲讲。<select>标签里的 id 必须和对应的 Mapper 接口里的方法名一样,resultType 就是咱们要返回的实体类类型,这里是 User。在 Java 代码里,咱们得先获取一个 SqlSession,这就像是打开了和数据库沟通的大门:
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();

image.gif

这里的 inputStream 是读取核心配置文件得到的,先别管它怎么来的,重点是拿到 SqlSession 后,咱们就能调用 Mapper 方法了:

UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.getUserById(1);
System.out.println(user);

image.gif

这里通过 getMapper 方法拿到 UserMapper 的代理对象,然后调用 getUserById 方法,传入要查询的用户 ID,就能拿到对应的 User 对象,最后打印出来看看是不是咱们想要的结果。要是查询所有用户,SQL 语句改改就行:

<select id="getAllUsers" resultType="User">
    select * from users
</select>

image.gif

Java 代码里调用 getAllUsers 方法就能拿到所有用户的列表啦,是不是挺简单的?

  1. 插入:插入新用户也不难,用<insert>标签,比如:
<insert id="addUser" useGeneratedKeys="true" keyProperty="id">
    insert into users (username, password, email)
    values (#{username}, #{password}, #{email})
</insert>

image.gif

这里的 useGeneratedKeys 和 keyProperty 很重要,它能让数据库自动生成主键,并且把主键值赋给实体类的 id 属性,这样咱们插入完数据后,就能直接拿到新生成的主键值啦。在 Java 代码里:

User newUser = new User(null, "张三", "123456", "zhangsan@example.com");
int rows = userMapper.addUser(newUser);
sqlSession.commit();
if (rows > 0) {
    System.out.println("插入成功,新用户 ID:" + newUser.getId());
}

image.gif

先创建一个新的 User 对象,调用 addUser 方法插入,然后提交事务,判断返回的行数,如果大于 0 就说明插入成功,还能拿到新用户的 ID,是不是很方便?

  1. 更新:更新用户信息用<update>标签,比如说咱们要更新用户的密码:❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️
<update id="updateUserPassword">
    update users
    <set>
        password = #{password}
    </set>
    where id = #{id}
</update>

image.gif

这里用<set>标签很巧妙,它能避免在更新多个字段时出现多余的逗号,保证 SQL 语法正确。在 Java 代码里:

User updateUser = new User(1, null, "newpassword", null);
int rows = userMapper.updateUserPassword(updateUser);
sqlSession.commit();
if (rows > 0) {
    System.out.println("更新成功");
}

image.gif

创建一个包含要更新字段的 User 对象,调用 updateUserPassword 方法,提交事务,判断返回行数确定是否更新成功。要是有多个字段要更新,就在<set>标签里多写几个就行,像这样:

<update id="updateUserInfo">
    update users
    <set>
        username = #{username},
        password = #{password},
        email = #{email}
    </set>
    where id = #{id}
</update>

image.gif

在复杂的业务里,可能还涉及到事务控制,比如同时更新多个表的数据,就得保证要么全成功,要么全失败,这时候就得合理使用 MyBatis 的事务功能,后面再详细讲。

  1. 删除:删除用户就简单多了,用<delete>标签:
<delete id="deleteUserById">
    delete from users where id = #{id}
</delete>

image.gif

在 Java 代码里:

int rows = userMapper.deleteUserById(1);
sqlSession.commit();
if (rows > 0) {
    System.out.println("删除成功");
}

image.gif

调用 deleteUserById 方法,传入要删除的用户 ID,提交事务,判断返回行数。不过要注意,如果表之间有外键约束,直接删除可能会报错,得先处理好外键关系,保护好数据的完整性,别把数据删乱了。

❤️四、进阶特性探索

💛(一)动态 SQL 魔法

  1. 有时候咱们查询用户,条件不是固定的,可能根据用户名、年龄等多个条件组合查询,这时候动态 SQL 就派上用场了。用<if>标签,比如:💚💚💚💚
<select id="getUsersByCondition" resultType="User">
    select * from users
    <where>
        <if test="username!= null">
            and username like '%${username}%'
        </if>
        <if test="age!= null">
            and age = #{age}
        </if>
    </where>
</select>

image.gif

这里的<where>标签也很有用,它能自动帮咱们去掉多余的 and 或者 or,让 SQL 语法更正确。<if>标签里的 test 是条件判断,根据传入的参数决定要不要加这个查询条件。注意啊,这里用 ${} 和 #{} 有区别,#{} 能防止 SQL 注入,更安全,所以尽量用 #{},除非有特殊情况。这种动态 SQL 比咱们硬编码的 SQL 灵活多了,能满足各种复杂的查询需求。

  1. 要是条件更复杂,有优先级之分,就可以用<choose>、<when>、<otherwise>标签,比如:❤️❤️
<select id="getUserByPriority" resultType="User">
    select * from users
    <where>
        <choose>
            <when test="id!= null">
                and id = #{id}
            </when>
            <when test="username!= null">
                and username like '%${username}%'
            </when>
            <otherwise>
                and age > 18
            </otherwise>
        </choose>
    </where>
</select>

image.gif

这就像是一个多分支的选择结构,先看有没有 ID,如果有就按 ID 查,如果没有再看用户名,都没有就查年龄大于 18 的用户,这样代码简洁性大大提升,查询也更灵活。

  1. 还有个超厉害的<foreach>标签,在批量操作里用处很大。比如说批量插入用户列表:❤️❤️❤️❤️
<insert id="addUsersBatch">
    insert into users (username, password, email)
    values
    <foreach collection="userList" item="user" separator=",">
        (#{user.username}, #{user.password}, #{user.email})
    </foreach>
</insert>

image.gif

这里的 collection 是传入的集合参数名字,item 是集合里每个元素的别名,separator 是分隔符,这样就能一次性插入多条数据,比一条条插入快多了。批量删除也类似,把 SQL 语句改成 delete 就行,大家可以试试。对比单条插入,批量插入在性能上有巨大优势,特别是数据量大的时候,能节省好多时间,不过也要注意数据量太大可能会超出数据库的处理能力,得根据实际情况优化。

❤️(二)缓存机制揭秘

  1. MyBatis 有个很神奇的缓存机制,能提高查询性能。先说说一级缓存,它是在同一个 SqlSession 里起作用的。比如说咱们第一次查询一个用户:❤️❤️
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user1 = userMapper.getUserById(1);
System.out.println(user1);

image.gif

这时候 MyBatis 会把查询结果放到一级缓存里,要是咱们紧接着再查询一次同一个用户:

User user2 = userMapper.getUserById(1);
System.out.println(user2);

image.gif

你会发现,这次查询并没有真正去数据库查,而是直接从缓存里拿的,因为缓存命中了,速度超快。但要注意,一旦咱们关闭了 SqlSession,缓存就没了,就像咱们关了冰箱门,里面的东西就拿不到了。而且如果在缓存期间,数据库里的数据被别人改了,咱们缓存里的数据就可能不一致了,这时候就得小心使用,别被过期数据误导了。

  1. 再讲讲二级缓存,它的范围更大,是在整个 MyBatis 配置的范围内。咱们得先在 MyBatis 配置文件里开启全局缓存:❤️❤️❤️❤️❤️❤️
<configuration>
    <settings>
        <setting name="cacheEnabled" value="true"/>
    </settings>
</configuration>

image.gif

然后在 Mapper.xml 文件里配置缓存标签:

<cache eviction="LRU" flushInterval="60000" size="512" readOnly="true"/>

image.gif

❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️

这里的 eviction 是缓存淘汰策略,LRU 就是最近最少使用,flushInterval 是刷新间隔,size 是缓存大小,readOnly 是缓存是否只读,这些参数可以根据实际情况调整。不同命名空间的 Mapper 缓存是分开的,只有在同一个命名空间下的查询才会共享缓存。比如说咱们有个多表关联查询,涉及到用户表和订单表,在查询用户及其订单信息的时候,第一次查完,二级缓存会把结果存起来,下次再查,如果数据没变化,就能直接从缓存里拿,大大提升了性能。不过要是数据更新了,就得想办法更新缓存,不然又会出现数据不一致的问题,这也是个技术活,得好好琢磨。

❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️❤️



相关文章
|
13天前
|
供应链 监控 安全
对话|企业如何构建更完善的容器供应链安全防护体系
阿里云与企业共筑容器供应链安全
171328 12
|
16天前
|
供应链 监控 安全
对话|企业如何构建更完善的容器供应链安全防护体系
随着云计算和DevOps的兴起,容器技术和自动化在软件开发中扮演着愈发重要的角色,但也带来了新的安全挑战。阿里云针对这些挑战,组织了一场关于云上安全的深度访谈,邀请了内部专家穆寰、匡大虎和黄竹刚,深入探讨了容器安全与软件供应链安全的关系,分析了当前的安全隐患及应对策略,并介绍了阿里云提供的安全解决方案,包括容器镜像服务ACR、容器服务ACK、网格服务ASM等,旨在帮助企业构建涵盖整个软件开发生命周期的安全防护体系。通过加强基础设施安全性、技术创新以及倡导协同安全理念,阿里云致力于与客户共同建设更加安全可靠的软件供应链环境。
150294 32
|
24天前
|
弹性计算 人工智能 安全
对话 | ECS如何构筑企业上云的第一道安全防线
随着中小企业加速上云,数据泄露、网络攻击等安全威胁日益严重。阿里云推出深度访谈栏目,汇聚产品技术专家,探讨云上安全问题及应对策略。首期节目聚焦ECS安全性,提出三道防线:数据安全、网络安全和身份认证与权限管理,确保用户在云端的数据主权和业务稳定。此外,阿里云还推出了“ECS 99套餐”,以高性价比提供全面的安全保障,帮助中小企业安全上云。
201959 14
对话 | ECS如何构筑企业上云的第一道安全防线
|
6天前
|
存储 人工智能 安全
对话|无影如何助力企业构建办公安全防护体系
阿里云无影助力企业构建办公安全防护体系
1251 8
|
1天前
|
机器学习/深度学习 自然语言处理 PyTorch
深入剖析Transformer架构中的多头注意力机制
多头注意力机制(Multi-Head Attention)是Transformer模型中的核心组件,通过并行运行多个独立的注意力机制,捕捉输入序列中不同子空间的语义关联。每个“头”独立处理Query、Key和Value矩阵,经过缩放点积注意力运算后,所有头的输出被拼接并通过线性层融合,最终生成更全面的表示。多头注意力不仅增强了模型对复杂依赖关系的理解,还在自然语言处理任务如机器翻译和阅读理解中表现出色。通过多头自注意力机制,模型在同一序列内部进行多角度的注意力计算,进一步提升了表达能力和泛化性能。
|
6天前
|
人工智能 自然语言处理 程序员
通义灵码2.0全新升级,AI程序员全面开放使用
通义灵码2.0来了,成为全球首个同时上线JetBrains和VSCode的AI 程序员产品!立即下载更新最新插件使用。
1261 23
|
8天前
|
机器学习/深度学习 自然语言处理 搜索推荐
自注意力机制全解析:从原理到计算细节,一文尽览!
自注意力机制(Self-Attention)最早可追溯至20世纪70年代的神经网络研究,但直到2017年Google Brain团队提出Transformer架构后才广泛应用于深度学习。它通过计算序列内部元素间的相关性,捕捉复杂依赖关系,并支持并行化训练,显著提升了处理长文本和序列数据的能力。相比传统的RNN、LSTM和GRU,自注意力机制在自然语言处理(NLP)、计算机视觉、语音识别及推荐系统等领域展现出卓越性能。其核心步骤包括生成查询(Q)、键(K)和值(V)向量,计算缩放点积注意力得分,应用Softmax归一化,以及加权求和生成输出。自注意力机制提高了模型的表达能力,带来了更精准的服务。
|
6天前
|
消息中间件 人工智能 运维
1月更文特别场——寻找用云高手,分享云&AI实践
我们寻找你,用云高手,欢迎分享你的真知灼见!
506 21
1月更文特别场——寻找用云高手,分享云&AI实践
|
6天前
|
机器学习/深度学习 人工智能 自然语言处理
|
12天前
|
人工智能 自然语言处理 API
阿里云百炼xWaytoAGI共学课DAY1 - 必须了解的企业级AI应用开发知识点
本课程旨在介绍阿里云百炼大模型平台的核心功能和应用场景,帮助开发者和技术小白快速上手,体验AI的强大能力,并探索企业级AI应用开发的可能性。