MyBatis-Plus的使用

目录

1.创建数据库

2.创建springboot工程 

 添加MyBatis-Plus依赖

配置数据库

application.yml 的写法

application.properties 的写法

创建实体类和编写接口

创建实体类UserInfo

编写Mapper接⼝类 

CRUD单元测试

 MyBatis-Plus复杂操作

常见注解

@TableName

@TableField 

@TableId

条件构造器

QueryWrapper

UpdateWrapper

LambdaQueryWrapper

LambdaUpdateWrapper

条件判断式

自定义SQL


MyBatis-Plus(简称 MP)是⼀个MyBatis的增强⼯具,在MyBatis的基础上只做增强不做改变,为简化开 发.提⾼效率⽽⽣

⽀持数据库: PostgreSQL, MySQL, MariaDB, Oracle, SQL Server, OceanBase, H2, DB2... (任何能使⽤MyBatis进⾏增删改查,并且⽀持标准SQL的数据库应该都在MyBatis-Plus的⽀持范围内)

1.创建数据库

这里我使用的是mysql数据库,大家可以根据自己的喜好来选择自己喜欢的数据库

-- 创建数据库
DROP DATABASE IF EXISTS mybatis_plus_test;
CREATE DATABASE mybatis_plus_test DEFAULT CHARACTER SET utf8mb4;

-- 使用数据库
USE mybatis_plus_test;

-- 创建表 user_info
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 CURRENT_TIMESTAMP,
  `update_time` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8mb4;

-- 添加用户信息
INSERT INTO `user_info` (`username`, `password`, `age`, `gender`, `phone`) VALUES ('admin', 'admin', 18, 1, '18612340001');
INSERT INTO `user_info` (`username`, `password`, `age`, `gender`, `phone`) VALUES ('zhangsan', 'zhangsan', 18, 1, '18612340002');
INSERT INTO `user_info` (`username`, `password`, `age`, `gender`, `phone`) VALUES ('lisi', 'lisi', 18, 1, '18612340003');
INSERT INTO `user_info` (`username`, `password`, `age`, `gender`, `phone`) VALUES ('wangwu', 'wangwu', 18, 1, '18612340004');

运行完上面这段代码,数据库表就变成这样了 

2.创建springboot工程 

在创建springboot工程的时候就需要把mysql依赖添加进来

 添加MyBatis-Plus依赖

这里我们可以选择去官网查看复制,也可以选择复制我下面这段代码

官网地址:MyBatis-Plus 🚀 为简化开发而生

SpringBoot2版本

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.9</version>
</dependency>

 SpringBoot3版本

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-spring-boot3-starter</artifactId>
    <version>3.5.9</version>
</dependency>

如果在创建springboot工程的时候没有添加mysql依赖可以加上下面这段代码,反之不用

 <dependency>
     <groupId>com.mysql</groupId>
     <artifactId>mysql-connector-j</artifactId>
     <scope>runtime</scope>
 </dependency>

然后把自己需要的代码复制到 pom.xml 里面并放到相应的位置

配置数据库

找到 src 路径下面的 main 下面的 resources 下面的 application.properties

这里可以根据个人习惯把 application.properties 改成 application.yml 

application.yml 的写法

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

application.properties 的写法

#驱动类名称
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#数据库连接的url
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/mybatis_plus_test?characterEncoding=utf8&useSSL=false
#连接数据库的⽤⼾名
spring.datasource.username=root
#连接数据库的密码
spring.datasource.password=123456

常见的几个错误:

  1. 使用的数据库是否和自己配置的数据库正确,并且启动springboot工程的时候要启动相对应的数据库
  2. 连接的数据库名是否正确
  3. 账号密码是否正确

创建实体类和编写接口

创建实体类UserInfo

注意自己创建的mapper包和model包一定要和启动类在demo包下

首先创建一个 mapper 包和一个 model 包,然后在 mapper 下面写一个接口 UserInfoMapper ,在model 下新建一个类 UserInfo

import lombok.Data;

import java.util.Date;
@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;
}

想要使用@Data注解得先引入 lombok ,前面创建springboot 工程的时候已经一并添加进来了

当然如果不想用 lombok 也可以使用传统的 getter 和 setter ,效果是一样的,只不过看起来比较长

编写Mapper接⼝类 

MybatisPlus提供了⼀个基础的 BaseMapper 接⼝,已经实现了单表的CRUD,我们⾃定义的 Mapper只需要继承这个BaseMapper,就⽆需⾃⼰实现单表CRUD了 

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.model.UserInfo;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface UserInfoMapper extends BaseMapper<UserInfo> {

}

写成上面这个样子就好了,这里提醒一下,如果没有BaseMapper这个类可能是因为没有提示,这时候就需要自己手动敲出来了,也可能是因为 pom.xml 没有刷新,需要重新刷新一下pom.xml文件

CRUD单元测试

首先创建一个测试类,名字随便起,但是一定要记得在类的上方加上 @SpringBootTest 注解,

注入 UserInfoMapper 类

比如这里有一个select,当我们输入前面几个字母的时候,就会给提示,我们根据提示来选择自己需要的 sql 语句就好了

简单的增删改查大致就是下面这段代码,如果想了解更复杂的请往后看 

import com.example.model.UserInfo;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import static org.junit.jupiter.api.Assertions.*;
@SpringBootTest
class UserInfoMapperTest {
    @Autowired
    private UserInfoMapper userInfoMapper;

    //查询
    @Test
    void testSelect(){
        System.out.println(userInfoMapper.selectById(1));
    }

    //增加
    @Test
    void testInsert(){
        UserInfo userInfo = new UserInfo();
        userInfo.setUsername("xixi");
        userInfo.setPassword("haha");
        userInfo.setAge(18);
        userInfoMapper.insert(userInfo);
    }

    //改
    @Test
    void testUpdate(){
        UserInfo userInfo = new UserInfo();
        userInfo.setId(11);
        userInfo.setPassword("haha");
        userInfo.setAge(18);
        userInfoMapper.updateById(userInfo);
    }

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

}

 MyBatis-Plus复杂操作

常见注解

在上⾯的程序中,MyBatis是如何知道,我们要操作的是哪张表,表⾥有哪些字段呢?

我们来看下咱们Mapper的代码

@Mapper
public interface UserInfoMapper extends BaseMapper<UserInfo> {

}

UserInfoMapper 在继承 BaseMapper 时,指定了⼀个泛型,这个UserInfo就是与数据库表相对应的实 体类. MyBatis-Plus会根据这个实体类来推断表的信息.

默认情况下:

  1. 表名:实体类的驼峰表⽰法转换成蛇形表⽰法(下划线分割),作为表名.⽐如UserInfo->user_info
  2. 字段:根据实体类的属性名转换为蛇形表⽰法作为字段名.⽐如deleteFlag->delete_flag
  3. 主键:默认为id

那如果实体类和数据库不是按照上述规则定义的呢?MyBatis-Plus也给我们提供了⼀下注解,让我们标识表的信息.

@TableName

当类名自动转换之后不能和数据库名相匹配之后就会报错,比如我将UserInfo 写成了 Userinfo 此时类名自动转换之后就不能与数据库名相匹配了,就会报类似下面这个错误

那如果我们就想使用这个类名呢?此时就需要拿出我们的@TableName注解

使用方法就是在类上面加上@TableName注解,里面写上对应的数据库表名,一定不能写错

@TableField 

这个注解和@TableName相似,这个是重新映射字段名与数据库字段

@TableId

如果userid不是主键,那么就需要使用@TableId,里面的id就是指定的数据库的主键名

如果属性名和字段名不⼀致,需要在 @TableId 指明对应的字段名

属性名和字段⼀致的情况下,直接加 @TableId 注解就可以.

type:用于指定主键类型,包括 IdType.AUTOIdType.INPUTIdType.NONE 等。常用的有

  • IdType.AUTO:自增主键,适用于自增长类型的主键。
  • IdType.INPUT:手动输入主键值,适用于需要手动指定主键值的情况。
  • IdType.NONE:无主键,适用于没有主键的情况。

条件构造器

QueryWrapper

这是一个可以用来自定义查询语句的,无论是修改,删除,查询都可以使用,相当于where语句部分

例如这个 SQL 语句原本是下面这样的

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

我们想利用QueryWrapper来完成应该怎么做呢?请看下面这段代码

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

解释:

  • UserInfo就是你定义的一个实体类,对应数据库中的某个表
  • .select("id", "username", "password", "age")就是指定查询结果中包含的字段
  • .eq("age", 18)就是设置一个等于条件,查询 age 等于 18 的记录(详情看下面)
  • .like("username", "min")就是设置一个模糊匹配条件,查询 username 包含 "min" 的记录
  • List<UserInfo> userInfos = userInfoMapper.selectList(userInfoQueryWrapper);这段代码的意思是调用userInfoMapper类的selectList方法并传入userInfoQueryWrapper构造器,返回值为List<UserInfo>

UpdateWrapper

对于更新,我们也可以直接使⽤UpdateWrapper,在不创建实体对象的情况下,直接设置更新字段和条 件

 UPDATE user_info SET delete_flag=0, age=5 WHERE id IN (1,2,3)
@Test
 void testUpdateByUpdateWrapper(){
 UpdateWrapper<UserInfo> updateWrapper = new UpdateWrapper<UserInfo>()
 .set("delete_flag",0)
 .set("age", 5)
 .in("id", List.of(1,2,3));
 userInfoMapper.update(updateWrapper);
 }

.set 是因为这个是更新语句,将“delete_flag” 改成 “0”,判断条件就是 id 等于 “1,2,3” 的

LambdaQueryWrapper

QueryWrapper和UpdateWrapper存在⼀个问题,就是需要写死字段名,如果字段名发⽣变更,可能会 因为测试不到位酿成事故.

@Test
 void testLambdaQueryWrapper(){
 QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>();
 queryWrapper.lambda()
 .select(UserInfo::getUsername, UserInfo::getPassword,UserInfo::getAge)
 .eq(UserInfo::getUserId, 1);
 userInfoMapper.selectList(queryWrapper).forEach(System.out::println);
 }

其实和QueryWrapper差不多,只不过是要多写一个 .lambda()

LambdaUpdateWrapper

@Test
 void testLambdUpdateByUpdateWrapper(){
 UpdateWrapper<UserInfo> updateWrapper = new UpdateWrapper<UserInfo>();
 updateWrapper.lambda()
 .set(UserInfo::getDeleteFlag, 0)
 .set(UserInfo::getAge, 5)
 .in(UserInfo::getUserId, List.of(1,2,3));
 userInfoMapper.update(updateWrapper);
 }

代码意思可以参考上面的

条件判断式

  1. 等于 (eq)

    • 方法:.eq("column", value)
    • 对应 SQL:column = value
  2. 不等于 (ne)

    • 方法:.ne("column", value)
    • 对应 SQL:column <> value
  3. 大于 (gt)

    • 方法:.gt("column", value)
    • 对应 SQL:column > value
  4. 大于等于 (ge)

    • 方法:.ge("column", value)
    • 对应 SQL:column >= value
  5. 小于 (lt)

    • 方法:.lt("column", value)
    • 对应 SQL:column < value
  6. 小于等于 (le)

    • 方法:.le("column", value)
    • 对应 SQL:column <= value
  7. 模糊匹配 (like)

    • 方法:.like("column", value)
    • 对应 SQL:column LIKE '%value%'
  8. 不模糊匹配 (notLike)

    • 方法:.notLike("column", value)
    • 对应 SQL:column NOT LIKE '%value%'
  9. 左模糊匹配 (likeLeft)

    • 方法:.likeLeft("column", value)
    • 对应 SQL:column LIKE 'value%'
  10. 右模糊匹配 (likeRight)

    • 方法:.likeRight("column", value)
    • 对应 SQL:column LIKE '%value'
  11. 为空 (isNull)

    • 方法:.isNull("column")
    • 对应 SQL:column IS NULL
  12. 非空 (isNotNull)

    • 方法:.isNotNull("column")
    • 对应 SQL:column IS NOT NULL
  13. 在某个集合中 (in)

    • 方法:.in("column", values)
    • 对应 SQL:column IN (value1, value2, ...)
  14. 不在某个集合中 (notIn)

    • 方法:.notIn("column", values)
    • 对应 SQL:column NOT IN (value1, value2, ...)
  15. 介于某个范围之间 (between)

    • 方法:.between("column", value1, value2)
    • 对应 SQL:column BETWEEN value1 AND value2
  16. 不在某个范围之间 (notBetween)

    • 方法:.notBetween("column", value1, value2)
    • 对应 SQL:column NOT BETWEEN value1 AND value2
  17. 排序 (orderByAsc, orderByDesc)

    • 方法:.orderByAsc("column1", "column2")
    • 对应 SQL:ORDER BY column1 ASC, column2 ASC
    • 方法:.orderByDesc("column1", "column2")
    • 对应 SQL:ORDER BY column1 DESC, column2 DESC
  18. 分组 (groupBy)

    • 方法:.groupBy("column1", "column2")
    • 对应 SQL:GROUP BY column1, column2
  19. 聚合函数 (having)

    • 方法:.having("sum(column) > {0}", value)
    • 对应 SQL:HAVING sum(column) > value
  20. 自定义条件 (apply)

    • 方法:.apply("column = {0}", value)
    • 对应 SQL:column = value
  21. 逻辑与 (and)

    • 方法:.and(i -> i.eq("column1", value1).lt("column2", value2))
    • 对应 SQL:column1 = value1 AND column2 < value2
  22. 逻辑或 (or)

    • 方法:.or(i -> i.eq("column1", value1).lt("column2", value2))
    • 对应 SQL:column1 = value1 OR column2 < value2

这些大家作为参考就好,也可以去官网查看

自定义SQL

为了使⽤这⼀功能, mybatis-plus 版本不低于3.0.7

下面来举一个例子

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> queryUserByCustom(@Param(Constants.WRAPPER) Wrapper<UserInfo> wrapper);
 }

这里需要注意一点的是引包的时候不要引错了,得引入下面这个包才对,注意一定要是baomidou的,因为相似的代码实在太多了,一旦没引对,发生错误就不好排查

测试代码:

@Test
 void testQueryUserByCustom(){
 QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>()
 .eq("username","admin");
 userInfoMapper.queryUserByCustom(queryWrapper).forEach(System.out::println);
 }
  1. 参数命名:在⾃定义SQL时,传递Wrapper对象作为参数时,参数名必须为ew,或者使⽤注解@Param(Constants.WRAPPER)明确指定参数为Wrapper对象.
  2. 使用${ew.customSqlSegment}:在SQL语句中,使⽤ ${ew.customSqlSegment} 来引⽤Wrapper对象⽣成的SQL⽚段.
  3. 不⽀持基于entity的where语句:⾃定义SQL时,Wrapper对象不会基于实体类⾃动⽣成 where⼦句,你需要⼿动编写完整的SQL语句

需要注意的是MyBatis-Plus 在 MyBatis 的基础上只做增强不做改变,所以也⽀持XML的实现⽅式,实现方式和MyBatis一样,大家之前怎么用Mybatis实现的xml现在就怎么用MyBatis-Plus实现xml就好了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值