当前位置: 首页 > news >正文

更高的效率——MyBatis-plus

一、什么是MyBatis-plus?

MyBatis-plus是MyBatis的增强工具,在MyBatis基础上只做增强不做改变,可以简化基础的CRUD操作(通过继承 BaseMapper 接口可直接使用预定义的增删改查方法)


二、MyBatis-plus快速入门

2.1 准备工作

2.1.1 数据库数据准备
CREATE DATABASE mybatis_test DEFAULT CHARACTER SET utf8mb4;

-- 使用数据库
USE mybatis_test;

-- 创建表[用户表]
DROP TABLE IF EXISTS user_info;

CREATE TABLE `user_info` (
    `id` INT ( 11 ) NOT NULL AUTO_INCREMENT,
    `username` VARCHAR ( 127 ) NOT NULL,
    `password` VARCHAR ( 127 ) NOT NULL,
    `age` TINYINT ( 4 ) NOT NULL,
    `gender` TINYINT ( 4 ) DEFAULT '0' COMMENT '1-男 2-女 0-默认',
    `phone` VARCHAR ( 15 ) DEFAULT NULL,
    `delete_flag` TINYINT ( 4 ) DEFAULT 0 COMMENT '0-正常,1-删除',
    `create_time` DATETIME DEFAULT now(),
    `update_time` DATETIME DEFAULT now(),
    PRIMARY KEY ( `id` )
) ENGINE = INNODB DEFAULT CHARSET = utf8mb4;

-- 添加用户信息
INSERT INTO mybatis_test.user_info( username, `password`, age, gender, phone ) 
VALUES ( 'admin', 'admin', 18, 1, '18612340001' );

INSERT INTO mybatis_test.user_info( username, `password`, age, gender, phone ) 
VALUES ( 'zhangsan', 'zhangsan', 18, 1, '18612340002' );

INSERT INTO mybatis_test.user_info( username, `password`, age, gender, phone ) 
VALUES ( 'lisi', 'lisi', 18, 1, '18612340003' );

INSERT INTO mybatis_test.user_info( username, `password`, age, gender, phone ) 
VALUES ( 'wangwu', 'wangwu', 18, 1, '18612340004' );

2.1.2 项目准备

1.创建SpringBoot项目;

2.添加MyBatis-plus和MySQL依赖,配置数据库连接信息。

一、添加MyBatis-plus依赖(SpringBoot 3)和MySQL依赖

<dependency>
 <groupId>com.baomidou</groupId>
 <artifactId>mybatis-plus-spring-boot3-starter</artifactId>
 <version>3.5.5</version>
</dependency>
<dependency>
 <groupId>com.mysql</groupId>
 <artifactId>mysql-connector-j</artifactId>
 <scope>runtime</scope>
</dependency>

二、配置数据库连接信息

# 数据库连接配置 
spring:
 datasource:
 url: jdbc:mysql://127.0.0.1:3306/mybatis_test?
characterEncoding=utf8&useSSL=false
 username: root
 password: root
 driver-class-name: com.mysql.cj.jdbc.Driver

2.2 代码准备

 一、创建实体类UserInfo与表中字段对应

@Data
public class UserInfo {
    private Integer id;
    private String username;
    private String password;
    private Integer age;
    private Integer gender;
    private String phone;

    private Integer deleteFlag;
    private Date createTime;
    private Date updateTime;

}

 二、创建Mapper接口并继承BaseMapper

@Mapper
public interface UserInfoMapper extends BaseMapper<UserInfo> {
}

查看BaseMapper,可以发现其中已经准备了各种基础的SQL对应的方法:

这也就是为什么使用MyBatis-plus无需手动编写SQL以及对应方法的原因。


2.3 CRUD单元测试

@SpringBootTest
class DemoApplicationTests {

	@Autowired
	private UserInfoMapper userInfoMapper;
	@Test
	void selectById() {
		UserInfo userInfo = userInfoMapper.selectById(1);
		System.out.println(userInfo);
	}

	@Test
	void selectByIds() {
		List<UserInfo> userInfos = userInfoMapper.selectByIds(List.of(22,23,24));
		System.out.println(userInfos);
	}

	@Test
	void insert() {
		UserInfo userInfo = new UserInfo();
		userInfo.setUsername("王五");
		userInfo.setPhone("381200");
		userInfo.setGender(3);
		userInfo.setAge(19);
		userInfoMapper.insert(userInfo);
	}

	@Test
	void deleteById() {
		userInfoMapper.deleteById(1);
	}

	@Test
	void update() {
		UserInfo userInfo = new UserInfo();
		userInfo.setId(1);
		userInfo.setUsername("宫本");
		userInfoMapper.updateById(userInfo);
	}

}

测试结果如下:

全部执行成功


三、MyBatis-plus复杂操作

 3.1 Mybatis-plus常见注解

在上面的代码中,MyBatis是如何知道我们操作的是哪个表的?表中又有那些字段?观察一下前面的Mapper接口:

BaseMapper指定了一个泛型,这个UserInfo就是与相应表对应的实体类,Mybatis-plus会根据实体类来推断表的信息,默认情况下:

1.表名:由驼峰表示法转换为蛇形表示法(如UserInfo->user_info)

2.字段名:也是驼峰表示法转换为蛇形表示法(如deleteFlag->delete_flag)

3.主键:默认为id

当然,如果设计表时或编写实体类时没有按照标准定义类名/表名、属性名/字段名,MyBatis-plus就无法正确推断,此时就需要注解来标识类名对应的表名(或属性名对应的字段名)


3.1.1 @TableName

@TableName用于标识类所对应的表名是什么

我们先将类名UserInfo改为Userinfo:

现在,再次测试selectByIds方法:

可以看到结果报错了,提示userinfo这个表并不存在,可以看到由于命名的不规范导致MyBatis-plus无法正确推断表名,接下来使用注解@TableName标识:

@Data
@TableName("user_info")//告知MyBatis-plus这个类对应的是哪个表
public class Userinfo {
    private Integer id;
    private String username;
    private String password;
    private Integer age;
    private Integer gender;
    private String phone;
    private Integer deleteFlag;
    private Date createTime;
    private Date updateTime;
}

再次测试selectByIds方法:

程序执行成功。


3.1.2 @TableField

 @TableName用于标识属性所对应的字段名是什么

将属性deleteFlag改为deleteflag:

测试insert方法:

报错,提示字段deletefalg不存在,接下来,使用注解@TableFiled标识类中属性对应的字段名:

@Data
@TableName("user_info")
public class Userinfo {
    private Integer id;
    private String username;
    private String password;
    private Integer age;
    private Integer gender;
    private String phone;
    //告知MyBatis-plus这个属性对应的字段是什么
    @TableField("delete_flag")
    private Integer deleteflag;
    private Date createTime;
    private Date updateTime;
}

再次测试:

执行成功。


3.1.3 @TableId

 @TableId用于标识表中主键对应的属性是什么,一般将属性名id作为主键,但是,如果将id修改为userId,MyBatis-plus就无法识别了,此时可以使用@TableId注解的value属性标识主键,如:

测试方法和上面的两个注解类似,这里就不再测试了,下面我们要介绍的是@TableId的另一个重要属性——type

我们先测试insert方法,往user_info中插入一个新数据并观察:

可以看到,新插入的数据id是一个非常小的负数,这是因为@TableId注解的type属性默认值为IdType.ASSIGN_ID一般来说,主键默认为自增的,但是type属性的默认值并不是自增,接下来,修改type属性的值为IdType.AUTO

public class Userinfo {
    //将id设置为自增
    @TableId(type = IdType.AUTO)
    private Integer id;
    private String username;
    private String password;
    private Integer age;
    private Integer gender;
    private String phone;
    private Integer deleteFlag;
    private Date createTime;
    private Date updateTime;
}

再次测试insert方法:

可以看到,修啊给type后,id正常自增


3.2 打印MyBatis-plus日志

 在配置文件中添加以下配置即可:

mybatis-plus:
 configuration: # 配置打印 MyBatis⽇志 
   log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

3.3 条件构造器(Wrapper)

前面只是使用MyBatis-plus进行一些简单的CRUD操作,但是在实际应用中,可能还会在SQL语句中加入一些条件(如 id!=10 等),对于这种情况,MyBatis-plus为我们提供了一套强大的条件构造器(Wrapper),下面是主要的Wrapper类:

AbstractWrapper⼀个抽象基类,提供了所有Wrapper类共有的方法和属性
QueryWrapper⽤于构造查询条件,在AbstractWrapper的基础上拓展了⼀个select⽅法,允许指定查询字段
UpdateWrapper⽤于构造更新条件,可以在更新数据时指定条件
LambdaQueryWrapper基于Lambda表达式的查询条件构造器,它通过Lambda表达式来引用实体类的属性,从而避免了硬编码字段名
LambdaupdateWrapper基于Lambda表达式的更新条件构造器,它允许你使⽤Lambda表达式来指定更新字段和条件,同样避免了硬编码字段名的问题
3.3.1 QueryWrapper

 QueryWrapper只是一个条件构造器,并不是只能用于查询语句,其它的删除、更新语句也同样可以使用。

一、查询
使用构造器构造如下SQL:

SELECT id,username,password,age FROM user_info WHERE age = 18 AND username 
"%min%"

在测试代码中构造:

	@Test
	void testQueryWrapper(){
		QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>().select("id","username","age","password")
				.eq("age",18).like("username","%min%");
		List<UserInfo> userInfos = userInfoMapper.selectList(queryWrapper);
		userInfos.forEach(System.out::println);
	}

二、更新

使用构造器构造如下SQL:

UPDATE user_info SET delete_flag=? WHERE age < 20

测试代码:

@Test
	void testQueryWrapper2(){
		QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>().lt("age",20);
		UserInfo userInfo = new UserInfo();
		userInfo.setDeleteFlag(0);
		userInfoMapper.update(userInfo,queryWrapper);
	}

三、删除

使用构造器构造如下SQL:

DELETE FROM user_info WHERE age = 18

测试代码:

   @Test
    void testQueryWrapper3() {
        QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>().eq("age",18);
        userInfoMapper.delete(queryWrapper);
    }

在上面使用构造器的代码中,涉及到一些缩写的方法,这里列举出常见的缩写方法的含义:

       lt“less than” 的缩写,表示小于
       le“less than or equal to” 缩写,表示小于或等于
       ge“greater than or equal to”缩写 ,表示大于或等于
       gt“greater than”缩写,表示大于
       eq“equals”缩写,表示等于
       ne“not equals”缩写,表示不等于

 


3.3.2 UpdateWrapper

对于更新语句,可以直接使用UpdateWrapper构造器进行构造,这要就不必创建对应的实体类(相较于QueryWrapper,多了一个set和setSql方法)

一、set方法

使用UpdateWrapper构造器构造如下SQL:

UPDATE user_info SET delete_flag=0, age=5 WHERE id IN (1,2,3)

测试代码:

    @Test
    void testUpdateWrapper(){
        UpdateWrapper<UserInfo> updateWrapper = new UpdateWrapper<>();
        updateWrapper.set("delete_flag",0).in("id",List.of(1,2,3));
        userInfoMapper.update(updateWrapper);
    }

二、setSql方法(基于SQL更新)

  @Test
    void testUpdateWrapper2(){
        UpdateWrapper<UserInfo> updateWrapper = new UpdateWrapper<>();
        updateWrapper.setSql("age = age + 10").eq("id",1);
        userInfoMapper.update(updateWrapper);
    }

3.3.3 LambdaQueryWrapper

 前面的QueryWrapper和UpdateWrapper都有一个共同特点,就是将字段名写死了,如果后续字段名发生变化,这里也不会报错,对此MyBatis-Plus 给我们提供了一种基于Lambda表达式的条件构造器,它通过 Lambda 表达式来引用实体类的属性,从而避免了硬编码字段名,也提高了代码的可读性和可维护性.

使用LambdaQueryWrapper构造以下SQL:
 

UPDATE user_info SET delete_flag=? WHERE age < 20

测试代码:

@Test
    void lambdaQueryWrapper(){
        LambdaQueryWrapper<UserInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        UserInfo userInfo = new UserInfo();
        userInfo.setDeleteFlag(0);
        lambdaQueryWrapper.in(UserInfo::getId,List.of(1,2,3));
        userInfoMapper.update(userInfo,lambdaQueryWrapper);
    }

3.3.4 LambdaUpdateWrapper

 使用LambdaUpdateWrapper构造以下SQL:

UPDATE user_info SET delete_flag=0, age=5 WHERE id IN (1,2,3)

测试代码:
 

  @Test
    void lambdaUpdateWrapper(){
        LambdaUpdateWrapper<UserInfo> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.set(UserInfo::getDeleteFlag,5).set(UserInfo::getAge,5).in(UserInfo::getId,List.of(1,2,3));
        userInfoMapper.update(lambdaUpdateWrapper);
    }

3.4 自定义SQL

 对于更加复杂的查询语句(如子查询),可能无法直接使用条件构造器完成,因此,MyBatis-plus提供了自定义SQL的功能,可以利用Wrapper构造查询条件,再结合Mapper编写SQL

使用自定义SQL完成以下查询:

select id,username,password,age FROM user_info WHERE username = "admin"

对应的Mapper:

@Mapper
public interface UserInfoMapper extends BaseMapper<UserInfo> {
    @Select("select id,username,password,age from user_info ${ew.customSqlSegment}")
    List<UserInfo> selectUserInfoByCondition (@Param(Constants.WRAPPER) Wrapper<UserInfo> ew);
}

测试代码:
 

  @Test
    void selectUserInfoByCondition() {
        QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.lt("age",20);
        userInfoMapper.selectUserInfoByCondition(queryWrapper).forEach(System.out::println);
    }

 使用自定义SQL,由几个注意事项:

• 参数命名:在自定义 SQL 时, 传递 Wrapper 对象作为参数时, 参数名必须为 ew ,或者使用注解 @Param(Constants.WRAPPER) 明确指定参数为 Wrapper 对象. 

• 使用 ${ew.customSqlSegment} 在 SQL 语句中,使用 ${ew.customSqlSegment} 来 引用 Wrapper 对象生成的 SQL 片段. 

• 不支持基于 entity 的 where 语句自定义 SQL 时,Wrapper 对象不会基于实体类自动生成  where 子句,你需要手动编写完整的 SQL 语句.

相关文章:

  • uniapp 获取dom信息(封装获取元素信息工具函数)
  • 多线程的三种实现方式
  • 基于单片机的智能奶茶机(论文 +源码)
  • 【ESP32】ESP32与MQTT通信:实现传感器数据监测与设备控制
  • GreenPlum学习
  • rsync备份(理论篇)
  • Keepalive+LVS+Nginx+NFS高可用架构
  • AI提示词(Prompt)设计优化方案 | 高效使用 AI 工具
  • 企业文档怎么保证安全传输?
  • jQuery Mobile 方向改变事件详解
  • Codeforces Round 1014 (Div. 2)(A-D)
  • pandas【9】数据合并concat/_append
  • 蓝桥云客 岛屿个数
  • Python if else while for 学习笔记
  • 基于Python的图书馆信息管理系统研发
  • 探寻性能优化:如何衡量?如何决策?
  • Cesium 全面介绍
  • 蓝桥与力扣刷题(34 在排序数组中查找元素的第一个和最后一个位置)
  • HTTP常见状态码分析
  • ICDE 2025[Tutorial]| 基于时间序列和时空数据的数据驱动决策
  • 机械毕业设计代做网站/google关键词工具
  • wordpress网站防采集/百度下载安装
  • 人流什么时间做 新闻源网站/如何自己创造一个网站平台
  • 司机找事做那个网站靠谱/网站快速排名优化报价
  • 五金设备网站建设/seo工作职责
  • 江门有什么网站推广/3步打造seo推广方案