SpringBoot + Mybatis系列教程之 CURD 基本使用姿势

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: mybatis 作为数据的 ORM 框架,在国内的应用市场还是非常可观的,当初刚开始工作时使用 spring + mybatis 进行开发,后来也使用过 hibernate, jdbctemplate, jooq,mybatisplus 等其他的一些框架,就个人使用感触来讲 jooq 的使用姿势和写 sql 差不多,基本上可以会写 sql 的无需额外的培训,立马可以上手;

image.png


mybatis 作为数据的 ORM 框架,在国内的应用市场还是非常可观的,当初刚开始工作时使用 spring + mybatis 进行开发,后来也使用过 hibernate, jdbctemplate, jooq,mybatisplus 等其他的一些框架,


就个人使用感触来讲 jooq 的使用姿势和写 sql 差不多,基本上可以会写 sql 的无需额外的培训,立马可以上手;


hibernate 最大的特点就是借助方法名来映射 sql 语句,非常有特点,但是当查询条件复杂一些的话,对小白而言就没有那么友好了;


而 jdbctemplate,这个在小项目,轻量的 db 操作中,用起来还是很爽的,非常灵活,但是也有一些点需要特别注意,比如 queryForObject,查不到数据时抛异常而不是返回 null;


至于 mybatis 以及衍生的 mybatis-plus,也就是接下来的主角了,它的特点如何,为什么受到国内大量开发者的追捧,将它作为 db 操作的第一 ORM 框架,让我们看完之后再说


I. 基础环境搭建



接下来的 Mybatis 的项目演示,主要是在 SpringBoot 的环境下运行,底层的数据库采用 MySql,对应的版本信息如下


  • springboot: 2.2.0.RELEASE
  • mysql: 5.7.22


1. SpringBoot 项目配置


关于 SpringBoot 的项目创建过程省略,下面是核心的 pom 依赖

<dependencies>
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>2.2.0</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
</dependencies>
复制代码


核心的依赖mybatis-spring-boot-starter,至于版本选择,到 mvn 仓库中,找最新的


另外一个不可获取的就是 db 配置信息,appliaction.yml

spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/story?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
    username: root
    password:
复制代码


2. 数据库准备


在本地数据库中,新增了一个表如下


CREATE TABLE `money` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(20) NOT NULL DEFAULT '' COMMENT '用户名',
  `money` int(26) NOT NULL DEFAULT '0' COMMENT '钱',
  `is_deleted` tinyint(1) NOT NULL DEFAULT '0',
  `create_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`),
  KEY `name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=551 DEFAULT CHARSET=utf8mb4;
复制代码


接下来本文涉及到的 CURD 都是针对这张表来说的


II. MyBatis CURD



接下来我们将从 0 到 1,实现基于 mybatis 进行 mysql 操作的全流程


1. 基本对象


经常使用 Mybatis 的小伙伴可能知道,操作一个 db,通常会伴随几个不可或缺的东西


  • 数据库实体类:可以理解为数据库表锁映射到的 Java Bean 对象
  • Mapper 接口:interface 类,其中定义 db 的操作方法
  • xml 文件:与上面接口对应,xml 文件中写实际的 sql


mybatis 推荐的玩法是借助 xml 来写 sql,但是官方也提供了注解的方式,因此 xml 文件并不是必须的;后面会介绍注解的操作方式;本文将主要是传统的 xml 配套使用姿势

针对上面这张表,第一步定义实体类MoneyPo


@Data
@NoArgsConstructor
@AllArgsConstructor
public class MoneyPo {
    private Integer id;
    private String name;
    private Long money;
    private Integer isDeleted;
    private Timestamp createAt;
    private Timestamp updateAt;
}
复制代码
  • 上面的三个注解属于 lombok 的知识点,有不清楚的小伙伴可以搜索一下


接下来是 Mapper 接口, MoneyMapper如下

// 注意这个@Mapper注解,用于表明这个接口属于Mybatis的Mapper对象
@Mapper
public interface MoneyMapper {
}
复制代码


然后是 Mapper 接口对应的 xml 文件MoneyMapper.xml


注意 xml 文件放在资源文件resources下面,且 xml 文件的目录结构,与上面的 Mapper 接口的包路径保持完全一致 (why? 参看博文 【DB 系列】SpringBoot 系列 Mybatis 之 Mapper 接口与 Sql 绑定几种姿势)

image.png

<?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.git.hui.boot.mybatis.mapper.MoneyMapper">
</mapper>
复制代码


2. 数据插入


前面的三步骤,将我们需要的实体类,接口对象,xml 文件都初始化完毕,接下来就是进入我们的 CURD 环节,实现数据库的增删改查,这里主要使用insert标签


比如我们现在希望插入一条数据,首先需要做的就是在 Mapper 接口中定义一个方法

int savePo(@Param("po") MoneyPo po);
复制代码


接着就是在 xml 文件中对应的 sql

<insert id="savePo" parameterType="com.git.hui.boot.mybatis.entity.MoneyPo" useGeneratedKeys="true"
        keyProperty="po.id">
  INSERT INTO `money` (`name`, `money`, `is_deleted`)
  VALUES
(#{po.name}, #{po.money}, #{po.isDeleted});
</insert>
复制代码


2.1 解析说明


注意上面的 xml 文件


  • parameterType: 用于指定传参类型
  • useGenerateKeys + keyProperty: 表明需要将插入 db 的主键 id,会写到这个实体类的 id 字段上
  • sql 语句传参:形如#{},大括号里面填写变量名,上面用的是po.name,po 为接口定义中的参数名,这个就表示使用 po 对象的 name 成员,作为 db 的 name 字段


接下来就是重要知识点:


  • 传参除了使用 #{}之外,还可以使用 ${},区别在于前面为参数参数占位,后面为字符串替换,因此存在 sql 注入的风险


举例说明

select * from money where id=${id}
select * from money where id=#{id}
复制代码


针对上面这两个 sql,当id = 1 or 1=1,对应的两个 sql 变成

-- 第一个sql会返回所有的数据
select * from money where id = 1 or 1 =1
-- 下面这个会抛sql异常
select * from money where id = '1 or 1=1'
复制代码


2.2 批量插入


除了上面的单挑插入,批量插入也是 ok 的,和前面的使用姿势差不多


int batchSave(@Param("list") List<MoneyPo> list);
复制代码


对应的 sql 如下

<insert id="batchSave" parameterType="com.git.hui.boot.mybatis.entity.MoneyPo"  useGeneratedKeys="true" keyProperty="id">
    insert ignore into `money` (`name`, `money`, `is_deleted`)
    values
    <foreach collection="list" item="item" index="index" separator=",">
        (#{item.name}, #{item.money}, #{item.isDeleted})
    </foreach>
</insert>
复制代码


对于 foreach 标签的说明,会放在后面的博文中专门进行介绍,这里简单理解为遍历即可


3. 数据查询


查询可以说是我们日常开发中最常见的情况了,这里先给出简单的查询 demo,至于更复杂的查询条件(如联表,子查询,条件查询等)在后面的博文中进行介绍

如根据主键进行查询,主要借助select标签来实现


MoneyPo findById(int id);
复制代码


对应的 sql

<resultMap id="BaseResultMap" type="com.git.hui.boot.mybatis.entity.MoneyPo">
    <id column="id" property="id" jdbcType="INTEGER"/>
    <result column="name" property="name" jdbcType="VARCHAR"/>
    <result column="money" property="money" jdbcType="INTEGER"/>
    <result column="is_deleted" property="isDeleted" jdbcType="TINYINT"/>
    <result column="create_at" property="createAt" jdbcType="TIMESTAMP"/>
    <result column="update_at" property="updateAt" jdbcType="TIMESTAMP"/>
</resultMap>
<sql id="money_po">
  id, name, money, is_deleted, create_at, update_at
</sql>
<select id="findById" parameterType="java.lang.Integer" resultMap="BaseResultMap">
    select
    <include refid="money_po"/>
    from money where id=#{id}
</select>
复制代码


重点关注下上面的实现,select 语句内容比较简单,但是有几个需要注意的点


  • sql 标签:内部定义需要查询的 db 字段,最大的特点是供后面的查询语句,通过include来引入,从而实现代码片段的复用
  • resullMap 标签:从 db 字段与 MoneyPo 实体类对比,我们可以知道部分字段名不是完全一样,如 db 中使用下划线,java 中使用驼峰,那么 db 字段与 java 成员变量如何映射呢?这里使用result标签来指定两者的映射关系,以及类型

(上面这个相信会始终伴随各位小伙伴的开发生涯)


4. 数据更新


更新主要借助update标签,相比较上面的两个,它的知识点就比较少了


int addMoney(@Param("id") int id, @Param("money") int money);
复制代码


对应的 sql 如下

<update id="addMoney" parameterType="java.util.Map">
    update money set money=money+#{money} where id=#{id}
</update>
复制代码


说明

  • 上面标签中的 parameterType,在这里实际上是可以省略的
  • @Param注解:主要用于指定参数名,在 xml 中可以使用内部定义的名字来作为参数变量;如果不加上这个注解,在 xml 中,参数变量则使用param0, param1来替代


5. 数据删除


删除使用delete标签

int delPo(@Param("id") int id);
复制代码


对应的 sql 如下

<delete id="delPo" parameterType="java.lang.Integer">
    delete from money where id = #{id,jdbcType=INTEGER}
</delete>
复制代码


6. 使用演示


上面的 mapper 接口中定义了完整的 CURD,接下来就是使用这个 Mapper 接口来实现交互了,在 Spring 中,使用姿势就非常简单了,直接当一个 Spring Bean 对象注入到 service 类中即可


@Repository
public class MoneyRepository {
    @Autowired
    private MoneyMapper moneyMapper;
    public void testBasic() {
        MoneyPo po = new MoneyPo();
        po.setName("mybatis user");
        po.setMoney((long) random.nextInt(12343));
        po.setIsDeleted(0);
        moneyMapper.savePo(po);
        System.out.println(po);
        MoneyPo out = moneyMapper.findById(po.getId());
        System.out.println("query:" + out);
        moneyMapper.addMoney(po.getId(), 100);
        System.out.println("after update:" + moneyMapper.findById(po.getId()));
        moneyMapper.delPo(po.getId());
        System.out.println("after del:" + moneyMapper.findById(po.getId()));
    }
}
复制代码


执行输出结果如下

MoneyPo(id=552, name=mybatis user, money=7719, isDeleted=0, createAt=null, updateAt=null)
query:MoneyPo(id=552, name=mybatis user, money=7719, isDeleted=0, createAt=2021-08-01 11:47:23.0, updateAt=2021-08-01 11:47:23.0)
after update:MoneyPo(id=552, name=mybatis user, money=7819, isDeleted=0, createAt=2021-08-01 11:47:23.0, updateAt=2021-08-01 11:47:23.0)
after del:null
复制代码


7. 小结


相信各位小伙伴看到这里,搭建一个 mybatis 实现数据库的 CURD 的项目应该是问题不大了,本文的主要知识点如下


  • mybatis 项目的三套件:实体类 + mapper 接口 + xml 文件
  • 数据库的增删改查


其中有一些知识点比较重要,本文只是抛出来了,有兴趣的小伙伴可以持续关注后续更新


下面这些知识点,后面会进行更详细的说明


  • 如何获取插入数据的主键 id
  • 批量场景下的foreach标签使用
  • 数据库表结构与 java 实体类的映射 resultMap标签
  • Mapper 接口与 xml 文件的关联方式
  • Mapper 接口如何被扫描到,并被 Spring bean 对象
  • Mapper 接口与 xml 的传参方式 @Param注解
  • sql 参数替换的两种写法 ${}, #{}
  • 传参类型,返回值类型定义
  • 代码复用片段sql标签



相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
3天前
|
SQL Java 数据库连接
【MyBatisPlus·最新教程】包含多个改造案例,常用注解、条件构造器、代码生成、静态工具、类型处理器、分页插件、自动填充字段
MyBatis-Plus是一个MyBatis的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。本文讲解了最新版MP的使用教程,包含多个改造案例,常用注解、条件构造器、代码生成、静态工具、类型处理器、分页插件、自动填充字段等核心功能。
【MyBatisPlus·最新教程】包含多个改造案例,常用注解、条件构造器、代码生成、静态工具、类型处理器、分页插件、自动填充字段
|
12天前
|
SQL 缓存 Java
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
本文详细介绍了MyBatis的各种常见用法MyBatis多级缓存、逆向工程、分页插件 包括获取参数值和结果的各种情况、自定义映射resultMap、动态SQL
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
|
1月前
|
Java 数据库连接 Maven
mybatis使用一:springboot整合mybatis、mybatis generator,使用逆向工程生成java代码。
这篇文章介绍了如何在Spring Boot项目中整合MyBatis和MyBatis Generator,使用逆向工程来自动生成Java代码,包括实体类、Mapper文件和Example文件,以提高开发效率。
105 2
mybatis使用一:springboot整合mybatis、mybatis generator,使用逆向工程生成java代码。
|
1月前
|
SQL JSON Java
mybatis使用三:springboot整合mybatis,使用PageHelper 进行分页操作,并整合swagger2。使用正规的开发模式:定义统一的数据返回格式和请求模块
这篇文章介绍了如何在Spring Boot项目中整合MyBatis和PageHelper进行分页操作,并且集成Swagger2来生成API文档,同时定义了统一的数据返回格式和请求模块。
52 1
mybatis使用三:springboot整合mybatis,使用PageHelper 进行分页操作,并整合swagger2。使用正规的开发模式:定义统一的数据返回格式和请求模块
|
19天前
|
SQL 存储 数据库
深入理解@TableField注解的使用-MybatisPlus教程
`@TableField`注解在MyBatis-Plus中是一个非常灵活和强大的工具,能够帮助开发者精细控制实体类与数据库表字段之间的映射关系。通过合理使用 `@TableField`注解,可以实现字段名称映射、自动填充、条件查询以及自定义类型处理等高级功能。这些功能在实际开发中,可以显著提高代码的可读性和维护性。如果需要进一步优化和管理你的MyBatis-Plus应用程
92 3
|
1月前
|
前端开发 Java Apache
Springboot整合shiro,带你学会shiro,入门级别教程,由浅入深,完整代码案例,各位项目想加这个模块的人也可以看这个,又或者不会mybatis-plus的也可以看这个
本文详细讲解了如何整合Apache Shiro与Spring Boot项目,包括数据库准备、项目配置、实体类、Mapper、Service、Controller的创建和配置,以及Shiro的配置和使用。
288 1
Springboot整合shiro,带你学会shiro,入门级别教程,由浅入深,完整代码案例,各位项目想加这个模块的人也可以看这个,又或者不会mybatis-plus的也可以看这个
|
1月前
|
Java 关系型数据库 MySQL
springboot学习五:springboot整合Mybatis 连接 mysql数据库
这篇文章是关于如何使用Spring Boot整合MyBatis来连接MySQL数据库,并进行基本的增删改查操作的教程。
64 0
springboot学习五:springboot整合Mybatis 连接 mysql数据库
|
1月前
|
SQL Java 数据库连接
mybatis使用二:springboot 整合 mybatis,创建开发环境
这篇文章介绍了如何在SpringBoot项目中整合Mybatis和MybatisGenerator,包括添加依赖、配置数据源、修改启动主类、编写Java代码,以及使用Postman进行接口测试。
16 0
mybatis使用二:springboot 整合 mybatis,创建开发环境
|
1月前
|
Java 数据库连接 API
springBoot:后端解决跨域&Mybatis-Plus&SwaggerUI&代码生成器 (四)
本文介绍了后端解决跨域问题的方法及Mybatis-Plus的配置与使用。首先通过创建`CorsConfig`类并设置相关参数来实现跨域请求处理。接着,详细描述了如何引入Mybatis-Plus插件,包括配置`MybatisPlusConfig`类、定义Mapper接口以及Service层。此外,还展示了如何配置分页查询功能,并引入SwaggerUI进行API文档生成。最后,提供了代码生成器的配置示例,帮助快速生成项目所需的基础代码。
|
1月前
|
Java 数据库连接 Maven
Spring整合Mybatis
Spring整合Mybatis