MybatisPlus方法详细使用,实现无SQL式开发

一、项目创建

可以选择SpringIntializr创建也可以使用Maven方式创建

选好之后点击下一步

这里只需要选中最基本的依赖项,后续依赖我们会在pom.xml中引入

二、引入依赖

spring Initializr创建项目需要在pom.xml文件的标签中添加如下依赖

        <!-- mysql数据库驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        
        <!-- lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        
        <!-- mybatis-plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.2</version>
        </dependency>
复制代码

如果是Maven方式创建项目,若想使用SpringBoot还需添加SpringBoot相关依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>MybatisPlus-Demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>MybatisPlus-Demo</name>
    <description>MybatisPlus-Demo</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- mysql数据库驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!-- lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!-- mybatis-plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.2</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
复制代码

三、创建数据库及引入数据库

1. 创建数据库

若已经有数据库则跳过至步骤二

我这里使用的是Navicat创建数据库

完成数据库创建后添加数据表

-- 判断要创建的表名称是否已经存在
DROP TABLE IF EXISTS student;
CREATE TABLE student(
	id BIGINT(20) NOT NULL COMMENT '主键ID,学号',
	name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',
	age INT(11) NULL DEFAULT NULL COMMENT '年龄',
	email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',
-- 设置id主键
	PRIMARY KEY (id),
-- 在id字段创建普通索引
	index(id)
);
-- 插入数据
INSERT INTO student (id, name, age, email) 
VALUES
(1001, 'Jone', 18, 'test1@baomidou.com'),
(1002, 'Jack', 20, 'test2@baomidou.com'),
(1003, 'Tom', 28, 'test3@baomidou.com'),
(1004, 'Sandy', 21, 'test4@baomidou.com'),
(1005, 'Billie', 24, 'test5@baomidou.com');
								
复制代码

创建表时详细索引参考->文档地址

2. 引入数据库

2.1 连接数据库

数据库连接语句在resource资源目录下的application.properties文件中书写

在MySQL8.0版本后,连接语句发生了变化(相关文档)。

MySQL8.0版本后的语句书写

# 数据库连接配置
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.url=jdbc:mysql://localhost:3306/mybatisPlus_demo?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# 配置日志 sql语句在执行时不可见,所以为了便于错误排查,需要通过日志打印语句。
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
注意:如果你是5.*数据库版本,就需要将com.mysql.cj.jdbc.Driver改为:com.mysql.jdbc.Driver。
复制代码

yml文件书写语句

server:
  port: 8080
spring:
  application:
    name: mybatis-plus
  datasource:
    url: jdbc:mysql://www.xlz.com/mybatis-plus?		useEncoding=utf8mb4&serverTimezone=Asia/Shanghai&useSSL=false
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver
复制代码

四、自动创建对应实体类及接口和xml文件

1 在idea中引入数据源

进入数据源后填写相关信息,点击下方测试链接通过后,点击确定按钮

2 使用Mybatis-generator自动创建

在导入完数据源后,找到要映射的数据表。右键选择mybatis-generator选项

进入mybatis-generate tool,填写对应信息

点击ok后,在指定路径总计生成三个文件(文件因路径不同,生成位置不同)。至此自动配置完成。

\

也可以使用语句生成

代码生成器(旧) | MyBatis-Plus

五、接口测试

一般创建SpringBoot项目中有内置Junit5的,这时可以通过使用快捷键alt+Insert快捷生成测试

书写如下代码,测试是否有数据输出。

@SpringBootTest
class StudentMapperTest{
    
    @Autowired
    StudentMapper studentMapper;
    
    @Test
    void selectByPrimaryKey (){
        Student student = studentMapper.selectByPrimaryKey (1001L);
        System.out.println (student);
    }
}
复制代码

六、日志打印

日志主要体现在当运行程序的时候,将会在控制台将会打印日志信息

使用在 application.xml 文件中加入

mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
复制代码

\

七、MybatisPlus常用注解

7.1 @MapperScan

作用: 为了集成Spring而写的注解,该注解主要是扫描某个包目录下的Mapper,将Mapper接口类交给Spring进行管理。

使用位置: 在Springboot启动类上添加

示例:

@SpringBootApplication
@MapperScan("com.example.mybatisplusdemo")
public class MybatisPlusDemoApplication{

	public static void main (String[] args){
		SpringApplication.run (MybatisPlusDemoApplication.class , args);
	}

}
复制代码

7.2 @Mapper

作用: 在接口类上添加了@Mapper,在运行时会生成相应的接口实现类,这个要一个一个去加,不如用@MapperScan全部扫描添加
添加位置: 接口类上面

示例:

@Mapper
public interface StudentMapper extends BaseMapper<Student>{
    ...
}
复制代码

7.3 @TableName

作用: 用于标识实体类对应的表名

添加位置: 实体类之上

示例:

@TableName("user")
public class User {
    ...
}
复制代码

7.4 @Data

作用: 简化开发,使用这个注解,就可以省略getter()、setter()、toString()、重写该类的equals()和hashCode()方法

使用位置: 实体类之上

示例:

@Data
public class User {
    ...
}
复制代码

7.5 @TableId

作用:

用于标识主键列,MyBatis-Plus在实现增删改查时,会默认将id作为主键列,在插入数据时,若对应字段为空,则默认使用基于雪花算法的策略生成id。

当使用@TableId(value = "id")语句时,若实体类和表中表示主键的不是id,而是其他字段,例如代码中的uid,MyBatis-Plus会自动识别uid为主键列,否则就会报错。

当使用@TableId(value = "id",type = IdType.AUTO)语句时,代表着使用数据库的自增策略,注意,该类型请确保数据库设置了id自增,否则无效!

@TableId的功能,也可以写在application.yml配置文件中,配置如下:

mybatis-plus:
  global-config:
    banner: false
    db-config:
      # 配置MyBatis-Plus操作表的默认前缀
      table-prefix: "t_"
      # 配置MyBatis-Plus的主键策略
      id-type: auto
  # 配置MyBatis日志
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
复制代码

使用位置: 主键映射字段之上

示例:

/**
 * student
 * @author 
 */
@Data
@TableName("mybatisplus_demo")
public class Student implements Serializable {
    /**
     * 主键ID,学号
     */
    @TableId(value = "id",type = IdType.AUTO )
    private Long id;
}
复制代码

7.6 @TableField

作用: 用于保证实体类中的属性名与数据表中字段名一致。

注: 若实体类中的属性使用的是驼峰命名风格,而表中的字段使用的是下划线命名风格。

例如实体类属性userName,表中字段user_name,此时MyBatis-Plus会自动将下划线命名风格转化为驼峰命名风格

若实体类中的属性和表中的字段不满足上述条件,例如实体类属性name,表中字段username,此时需要在实体类属性上使用@TableField("username")设置属性所对应的字段名

使用位置: 实体类除主键字段外其他映射字段之上

@Data
@TableName("mybatisplus_demo")
public class Student implements Serializable {
    /**
     * 主键ID,学号
     */
    @TableId(value = "id",type = IdType.AUTO )
    private Long id;

    /**
     * 姓名
     */
    @TableField(value = "name")
    private String name;
}
复制代码

7.7 @TableLogic

作用: 逻辑删除,并不会永久删除数据,实体类加上这个注解再执行删除方法的时候会变成修改。前台再根据所加注解字段进行显隐即可达到逻辑删除效果。

@Data
@TableName("mybatisplus_demo")
public class Student implements Serializable {
    /**
     * 主键ID,学号
     */
    @TableId(value = "id",type = IdType.AUTO )
    private Long id;

    /*
        删除标识
     
        @TableLogic(value=“原值”,delval=“修改值”)
        注解参数
            value = “” 未删除的值,默认值为0
            delval = “” 删除后的值,默认值为1
     */
    
    @TableField(value = "del")
    @TableLogic(value = "0",delval = "1")
    private Integer del;
}
复制代码

\

调用BaseMapper的deleteById(id)或者调用IService的removeById(id)

效果:
    没有@TableLogic注解调用deleteById/removeById,直接删除数据。
        SQL:delete from table where id = 1
    有注解走Update方法
        SQL:Update table set isDelete = 1 where id = 1
复制代码

\

7.8 @Param

作用:用于标识传入参数的名称

使用位置:形参列表

示例:

@Mapper
public interface StudentMapper extends BaseMapper<Student>{
       int insert(@Param (value = "record") Student record);
}
复制代码

与之对应的XML文件就可以使用${record}变量

7.9 @Version

作用: 可以在实体 bean 中使用@Version 注解,通过这种方式可添加对乐观锁定的支持,一个类中只能有一个@Version注解。

不可选属性

String



可选属性

int

Integer

Long

@Data
@TableName("mybatisplus_demo")
public class Student implements Serializable {
    /**
     * 主键ID,学号
     */
    @TableId(value = "id",type = IdType.AUTO )
    private Long id;

    /**
     * 版本号
     */
    @Version (value = "version")
    private int version;
}
复制代码

7.10 @EnumValue 和 JsonValue

@JsonValue
可以用在get方法或者属性字段上,一个类只能用一个,当加上@JsonValue注解时,该类的json化结果,只有这个get方法的返回值,而不是这个类的属性键值对.

案例: 男,女,后台存储的是1,2,前端展示的是男女

第一步:

创建枚举类,在需要存储数据库的属性上添加 @EnumValue注解,在需要前端展示的属性上添加 @JsonValue注解;

package com.demo.mybatisplus.constant;

import com.baomidou.mybatisplus.annotation.EnumValue;
import com.fasterxml.jackson.annotation.JsonValue;

public enum SexEnum {

    MAN(1, "男"),
    WOMAN(2, "女");

    @EnumValue
    private Integer key;

    @JsonValue
    private String display;

    SexEnum(Integer key, String display) {
        this.key = key;
        this.display = display;
    }

    public Integer getKey() {
        return key;
    }

    public String getDisplay() {
        return display;
    }
}
复制代码

第二步:

application.properties文件里添加配置,定义扫描枚举类的包路径;

#配置枚举 支持通配符 * 或者 ; 分割
mybatis-plus.type-enums-package=com.demo.mybatisplus.constant
#mybatis-plus.configuration.default-enum-type-handler=org.apache.ibatis.type.EnumOrdinalTypeHandler
复制代码

application.yml则配置

#配置枚举 支持通配符 * 或者 ; 分割
mybatis-plus:
  type-enums-package: com.demo.mybatisplus.constant
  configuration:
    default-enum-type-handler: org.apache.ibatis.type.EnumOrdinalTypeHandler
复制代码

第三步:

pojo中的sex属性设置为枚举SexEnum;

@ApiModelProperty(value = "性别")
    @TableField("sex")
    private SexEnum sex;
复制代码

测试:

@Test
public void insert() {
    UserInfo userInfo = new UserInfo();
    userInfo.setAge(22);
    userInfo.setName("李四");
    userInfo.setSex(SexEnum.WOMAN);
    userInfoMapper.insert(userInfo);
    System.out.println(userInfo);
}
复制代码

注意事项:

  1. @EnumValue标记的枚举类属性的类型要和数据库字段的类型对应,否则在查询数据的时候无法转化为枚举类型,并显示为null;
  2. 如果查询的时候,数据库字段的值匹配不到枚举,程序运行时并不会报错,而是显示为null;
  3. 在保存的时候,前端需要传递@JsonValue标记的枚举类属性的值,即"男/女";因为Enum的属性ordinal(int),在测试过程中,传枚举值在枚举类中的定义顺序(或者称为索引,顺序从0开始),也可以转换为相应的枚举值,比如:上面定义的SexEnum枚举,前端传0或者"0",会转换成MAN,传1或者"1"会转换成WOMAN;传其他值会报异常:com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type com.demo.mybatisplus.constant.SexEnum from String "3": not one of the values accepted for Enum class: [女, 男]或com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type com.demo.mybatisplus.constant.SexEnum from number 3: index value outside legal index range [0..2];

八、MybatisPlus常用方法

8.1 条件构造器 Wrapper


介绍 :

  • 上图绿色框为抽象类abstract
  • 蓝色框为正常class类,可new对象
  • 黄色箭头指向为父子类关系,箭头指向为父类

wapper介绍 :

  • Wrapper : 条件构造抽象类,最顶端父类,抽象类中提供4个方法西面贴源码展示
  • AbstractWrapper : 用于查询条件封装,生成 sql 的 where 条件
  • AbstractLambdaWrapper : Lambda 语法使用 Wrapper统一处理解析 lambda 获取 column。
  • LambdaQueryWrapper :看名称也能明白就是用于Lambda语法使用的查询Wrapper
  • LambdaUpdateWrapper : Lambda 更新封装Wrapper
  • QueryWrapper : Entity 对象封装操作类,不是用lambda语法
  • UpdateWrapper : Update 条件封装,用于Entity对象更新操作

\

常用条件

比较大小: (=,<>,>,>=,<,<=)

eq(R column, Object val); // 等价于 =,例: eq("name", "老王") ---> name = '老王'
ne(R column, Object val); // 等价于 <>,例: ne("name", "老王") ---> name <> '老王'
gt(R column, Object val); // 等价于 >,例: gt("name", "老王") ---> name > '老王'
ge(R column, Object val); // 等价于 >=,例: ge("name", "老王") ---> name >= '老王'
lt(R column, Object val); // 等价于 <,例: lt("name", "老王") ---> name < '老王'
le(R column, Object val); // 等价于 <=,例: le("name", "老王") ---> name <= '老王'
复制代码

范围:(between、not between、in、not in)

between(R column, Object val1, Object val2); // 等价于 between a and b, 例: between("age", 18, 30) ---> age between 18 and 30
   notBetween(R column, Object val1, Object val2); // 等价于 not between a and b, 例: notBetween("age", 18, 30) ---> age not between 18 and 30
   in(R column, Object... values); // 等价于 字段 IN (v0, v1, ...),例: in("age",{1,2,3}) ---> age in (1,2,3)
   notIn(R column, Object... values); // 等价于 字段 NOT IN (v0, v1, ...), 例: notIn("age",{1,2,3}) ---> age not in (1,2,3)
   inSql(R column, Object... values); // 等价于 字段 IN (sql 语句), 例: inSql("id", "select id from table where id < 3") ---> id in (select id from table where id < 3)
   notInSql(R column, Object... values); // 等价于 字段 NOT IN (sql 语句)
复制代码

模糊匹配:(like)

// 等价于 LIKE '%值%',例: like("name", "王") ---> name like '%王%'
like(R column, Object val); 
// 等价于 NOT LIKE '%值%',例: notLike("name", "王") ---> name not like '%王%'
notLike(R column, Object val); 
// 等价于 LIKE '%值',例: likeLeft("name", "王") ---> name like '%王'
likeLeft(R column, Object val); 
 // 等价于 LIKE '值%',例: likeRight("name", "王") ---> name like '王%'
likeRight(R column, Object val);
复制代码

空值比较:(isNull、isNotNull)

isNull(R column); // 等价于 IS NULL,例: isNull("name") ---> name is null
isNotNull(R column); // 等价于 IS NOT NULL,例: isNotNull("name") ---> name is not null
复制代码

分组、排序:(group、having、order)

groupBy(R... columns); // 等价于 GROUP BY 字段, ..., 例: groupBy("id", "name") ---> group by id,name
orderByAsc(R... columns); // 等价于 ORDER BY 字段, ... ASC, 例: orderByAsc("id", "name") ---> order by id ASC,name ASC
orderByDesc(R... columns); // 等价于 ORDER BY 字段, ... DESC, 例: orderByDesc("id", "name") ---> order by id DESC,name DESC
having(String sqlHaving, Object... params); // 等价于 HAVING ( sql语句 ), 例: having("sum(age) > {0}", 11) ---> having sum(age) > 11
复制代码

拼接、嵌套 sql:(or、and、nested、apply)

or(); // 等价于 a or b, 例:eq("id",1).or().eq("name","老王") ---> id = 1 or name = '老王'
or(Consumer<Param> consumer); // 等价于 or(a or/and b),or 嵌套。例: or(i -> i.eq("name", "李白").ne("status", "活着")) ---> or (name = '李白' and status <> '活着')
and(Consumer<Param> consumer); // 等价于 and(a or/and b),and 嵌套。例: and(i -> i.eq("name", "李白").ne("status", "活着")) ---> and (name = '李白' and status <> '活着')
nested(Consumer<Param> consumer); // 等价于 (a or/and b),普通嵌套。例: nested(i -> i.eq("name", "李白").ne("status", "活着")) ---> (name = '李白' and status <> '活着')
apply(String applySql, Object... params); // 拼接sql(若不使用 params 参数,可能存在 sql 注入),例: apply("date_format(dateColumn,'%Y-%m-%d') = {0}", "2008-08-08") ---> date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")
last(String lastSql); // 无视优化规则直接拼接到 sql 的最后,可能存若在 sql 注入。
exists(String existsSql); // 拼接 exists 语句。例: exists("select id from table where age = 1") ---> exists (select id from table where age = 1)
复制代码

QueryWrapper 条件:

select(String... sqlSelect); // 用于定义需要返回的字段。例: select("id", "name", "age") ---> select id, name, age
select(Predicate<TableFieldInfo> predicate); // Lambda 表达式,过滤需要的字段。
lambda(); // 返回一个 LambdaQueryWrapper
复制代码

UpdateWrapper 条件:

set(String column, Object val); // 用于设置 set 字段值。例: set("name", null) ---> set name = null
etSql(String sql); // 用于设置 set 字段值。例: setSql("name = '老李头'") ---> set name = '老李头'
lambda(); // 返回一个 LambdaUpdateWrapper```
复制代码

8.2 Page<>类

属性源码

public class Page<T> implements IPage<T> {
    private static final long serialVersionUID = 8545996863226528798L;
    // 用来存放查询出来的数据
    protected List<T> records;
    // 返回记录的总数
    protected long total;
    // 每页显示条数,默认 10
    protected long size;
    // 当前页,默认1
    protected long current;
    // 排序字段信息
    protected List<OrderItem> orders;
    // 自动优化 COUNT SQL,默认true
    protected boolean optimizeCountSql;
    // 是否进行 count 查询,默认true
    protected boolean isSearchCount;
    // 是否命中count缓存,默认false
    protected boolean hitCount;
    protected String countId;
    protected Long maxLimit;
}
复制代码

\

8.3 mapper层(接口定义层)可以用BaseMapper<>

例如

内部方法总览

方法详细介绍

汇总

【添加数据:(增)】
    int insert(T entity);              // 插入一条记录
注:
    T         表示任意实体类型
    entity    表示实体对象

【删除数据:(删)】
    int deleteById(Serializable id);    // 根据主键 ID 删除
    int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);  // 根据 map 定义字段的条件删除
    int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper); // 根据实体类定义的 条件删除对象
    int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList); // 进行批量删除
注:
    id        表示 主键 ID
    columnMap 表示表字段的 map 对象
    wrapper   表示实体对象封装操作类,可以为 null。
    idList    表示 主键 ID 集合(列表、数组),不能为 null 或 empty

【修改数据:(改)】
    int updateById(@Param(Constants.ENTITY) T entity); // 根据 ID 修改实体对象。
    int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper); // 根据 updateWrapper 条件修改实体对象
注:
    update 中的 entity 为 set 条件,可以为 null。
    updateWrapper 表示实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)

【查询数据:(查)】
    T selectById(Serializable id); // 根据 主键 ID 查询数据
    List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList); // 进行批量查询
    List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap); // 根据表字段条件查询
    T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper); // 根据实体类封装对象 查询一条记录
    Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper); // 查询记录的总条数
    List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper); // 查询所有记录(返回 entity 集合)
    List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper); // 查询所有记录(返回 map 集合)
    List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper); // 查询所有记录(但只保存第一个字段的值)
    <E extends IPage<T>> E selectPage(E page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper); // 查询所有记录(返回 entity 集合),分页
    <E extends IPage<Map<String, Object>>> E selectMapsPage(E page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper); // 查询所有记录(返回 map 集合),分页
注:
    queryWrapper 表示实体对象封装操作类(可以为 null)
    page 表示分页查询条件
复制代码

插入一条记录

int insert(T entity); 
复制代码
@Test
public void Insert_T(){
    Student student=new Student ();
    student.setAge (18);
    student.setEmail ("165@163.com");
    student.setName ("柳宗元");
    int insert = studentMapper.insert (student);
    System.out.println (insert==0?"插入失败":"插入成功");
}
复制代码

根据主键id删除

int deleteById(Serializable id);
复制代码

根据 map 定义字段的条件删除

int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
复制代码
@Test
public void deleteByMap_T(){
    // 通用删除操作 deleteByMap  map要写列名条件 不能是实体属性名
    Map<String, Object> map=new HashMap<> ();
    // 删除name列中,内容为Jone的记录
    map.put ("name","Jone");
    int count = studentMapper.deleteByMap (map);
    System.out.println (count==0?"删除失败":"删除成功");
}
复制代码

根据实体类定义的条件删除对象

 // 根据实体类定义的 条件删除对象 
int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper);
复制代码

进行批量删除

// 进行批量删除
// idList 表示主键 ID 集合(列表、数组),不能为 null 或 empty
int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList); 
复制代码
@Test
public void deleteBatchIds_T(){
    int count = studentMapper.deleteBatchIds (Stream.of (1012,1013).collect(Collectors.toList ()));
    System.out.println (count==0?"删除失败":"删除成功");
}
复制代码

根据 ID 修改实体对象。

int updateById(@Param(Constants.ENTITY) T entity); 
复制代码
@Test
public void updateByid_T(){
    Student student=new Student ();
    student.setAge (19);
    student.setEmail ("1623@163.com");
    student.setName ("白居易修改测试");
    student.setId (1030L);
    int count = studentMapper.updateById (student);
    System.out.println (count==0?"修改失败":"修改成功");
}
复制代码

根据 updateWrapper 条件修改实体对象

\

int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper);
复制代码

根据 主键 ID 查询数据

T selectById(Serializable id); 
复制代码
//示例
@Test
public void selectById_T(){
    Student student = studentMapper.selectById (1030L);
    System.out.println (student);
}
复制代码

进行批量查询

List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList); 
复制代码
@Test
public void selectBatchIds_T(){
    List<Student> students = studentMapper.selectBatchIds (Stream.of (1012 , 1013).collect (Collectors.toList ()));
    students.forEach (System.out :: println);
}

/*
 * ==>  Preparing: SELECT id,name,age,email FROM student WHERE id IN ( ? , ? )
 * ==> Parameters: 1012(Integer), 1013(Integer)
 * <==    Columns: id, name, age, email
 * <==        Row: 1012, 柳宗元, 18, 165@163.com
 * <==        Row: 1013, 柳宗元, 18, 165@163.com
 * <==      Total: 2
*/
复制代码

根据表字段名称查询

List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
复制代码
@Test
public void selectByMap(){
    HashMap<String, Object> map = new HashMap<> ();
    map.put ("name","柳宗元");
    map.put ("age","18");
    List<Student> students = studentMapper.selectByMap (map);
}

/*
 * ==>  Preparing: SELECT id,name,age,email FROM student WHERE name = ? AND age = ?
 * ==> Parameters: 柳宗元(String), 18(String)
 * <==    Columns: id, name, age, email
 * <==        Row: 1007, 柳宗元, 18, 165@163.com
 * <==        Row: 1008, 柳宗元, 18, 165@163.com
 * <==        Row: 1009, 柳宗元, 18, 165@163.com
 * <==      Total: 3
 */
复制代码

查询记录总条数

 Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
复制代码
@Test
public void selectCount_T(){
    // queryWrapper 表示实体对象封装操作类(可以为 null)
    Integer integer = studentMapper.selectCount (null);
    System.out.println (integer);
}

/*
 * ==>  Preparing: SELECT COUNT( * ) FROM student
 * ==> Parameters: 
 * <==    Columns: COUNT( * )
 * <==        Row: 54
 * <==      Total: 1
 */
复制代码

查询所有记录 List

List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper); 
复制代码
/*
* 查询所有name=柳宗元的记录
*/
@Test
public void selectList_T(){
    List<Student> students = studentMapper.selectList (new QueryWrapper<Student> ().eq ("name" , "柳宗元").);
    students.forEach (System.out :: println);
}

/*
 * ==>  Preparing: SELECT id,name,age,email FROM student WHERE (name = ?)
 * ==> Parameters: 柳宗元(String)
 * <==    Columns: id, name, age, email
 * <==        Row: 1007, 柳宗元, 18, 165@163.com
 * <==        Row: 1008, 柳宗元, 18, 165@163.com
 * <==        Row: 1009, 柳宗元, 18, 165@163.com
 * <==        Row: 1010, 柳宗元, 18, 165@163.com
 * <==      Total: 4
 */
复制代码

查询所有记录 Map

 List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper); 
复制代码
@Test
public void selectMaps_T(){
    List<Map<String, Object>> maps = studentMapper.selectMaps (new QueryWrapper<Student> ().eq ("name" , "柳宗元"));
    maps.forEach (item-> {
        item.forEach ((key, value)-> System.out.println (key+" --- "+value));
        System.out.println ();
    });
    
/*
 * ==>  Preparing: SELECT id,name,age,email FROM student WHERE (name = ?)
 * ==> Parameters: 柳宗元(String)
 * <==    Columns: id, name, age, email
 * <==        Row: 1007, 柳宗元, 18, 165@163.com
 * <==        Row: 1008, 柳宗元, 18, 165@163.com
 * <==        Row: 1009, 柳宗元, 18, 165@163.com
 * <==        Row: 1010, 柳宗元, 18, 165@163.com
 * <==      Total: 4
 */
复制代码

控制台打印信息

System.out.println (key+" --- "+value));

/* 
 * name ---- 柳宗元
 * id ---- 1007
 * age ---- 18
 * email ---- 165@163.com
 *
 * name ---- 柳宗元
 * id ---- 1008
 * age ---- 18
 * email ---- 165@163.com
 *
 * name ---- 柳宗元
 * id ---- 1009
 * age ---- 18
 * email ---- 165@163.com
 */
复制代码

查询所有记录(但只保存第一个字段的值)

建表时,通常 id 作为首字段。可以返回所有id

List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
复制代码
@Test
public void selectObjs_T(){
    List<Object> objects = studentMapper.selectObjs (new QueryWrapper<Student> ().likeRight ("name" , "白居易"));
    objects.forEach (System.out :: println);
}
/**
 * ==>  Preparing: SELECT id,name,age,email FROM student WHERE (name LIKE ?)
 * ==> Parameters: 白居易%(String)
 * <==    Columns: id, name, age, email
 * <==        Row: 1027, 白居易0, 19, 1623@163.com
 * <==        Row: 1028, 白居易1, 19, 1623@163.com
 * <==        Row: 1029, 白居易2, 19, 1623@163.com
 * <==        Row: 1030, 白居易修改测试, 19, 1623@163.com
 * <==        Row: 1031, 白居易4, 19, 1623@163.com
 * <==        Row: 1032, 白居易5, 19, 1623@163.com
 * <==        Row: 1033, 白居易6, 19, 1623@163.com
 * <==      Total: 7
 */
复制代码

控制台打印数据

objects.forEach (System.out :: println);

/**
 * 1027
 * 1028
 * 1029
 * 1030
 * 1031
 * 1032
 * 1033
 */
复制代码

查询所有记录 分页 List

 <E extends IPage<T>> E selectPage(E page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
复制代码
Page<Student> studentPage = studentMapper.selectPage (new Page<> (2 , 4) ,
				new QueryWrapper<Student> ().likeRight ("name" , "白居易"));
复制代码

查询所有记录 分页 Map

<E extends IPage<Map<String, Object>>> E selectMapsPage(E page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
复制代码
@Test
public void selectMapsPage_T(){
    Page<Map<String, Object>> mapPage = studentMapper.selectMapsPage (new Page<> (2 , 4) ,new QueryWrapper<Student> ().likeRight ("name" , "白居易"));
}
复制代码

8.4service层(接口方法)可以用IService<>

介绍:
使用 代码生成器 生成的 service 接口中,其继承了 IService 接口。
IService 内部进一步封装了 BaseMapper 接口的方法(当然也提供了更详细的方法)。
使用时,可以通过 生成的 mapper 类进行 CRUD 操作,也可以通过 生成的 service 的实现类进行 CRUD 操作。(当然,自定义代码执行也可)
此处简单介绍一下 IService 中封装的常用方法。

内部方法总览

方法详细介绍

汇总

【添加数据:(增)】
    default boolean save(T entity); // 调用 BaseMapper 的 insert 方法,用于添加一条数据。
    boolean saveBatch(Collection<T> entityList, int batchSize); // 批量插入数据
注:
    entityList 表示实体对象集合 
    batchSize 表示一次批量插入的数据量,默认为 1000

【添加或修改数据:(增或改)】
    boolean saveOrUpdate(T entity); // id 若存在,则修改, id 不存在则新增数据
   default boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper); // 先根据条件尝试更新,然后再执行 saveOrUpdate 操作
   boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize); // 批量插入并修改数据 

【删除数据:(删)】
    default boolean removeById(Serializable id); // 调用 BaseMapper 的 deleteById 方法,根据 id 删除数据。
    default boolean removeByMap(Map<String, Object> columnMap); // 调用 BaseMapper 的 deleteByMap 方法,根据 map 定义字段的条件删除
    default boolean remove(Wrapper<T> queryWrapper); // 调用 BaseMapper 的 delete 方法,根据实体类定义的 条件删除对象。
    default boolean removeByIds(Collection<? extends Serializable> idList); // 用 BaseMapper 的 deleteBatchIds 方法, 进行批量删除。
    
【修改数据:(改)】
    default boolean updateById(T entity); // 调用 BaseMapper 的 updateById 方法,根据 ID 选择修改。
    default boolean update(T entity, Wrapper<T> updateWrapper); // 调用 BaseMapper 的 update 方法,根据 updateWrapper 条件修改实体对象。
    boolean updateBatchById(Collection<T> entityList, int batchSize); // 批量更新数据

【查找数据:(查)】
    default T getById(Serializable id); // 调用 BaseMapper 的 selectById 方法,根据 主键 ID 返回数据。
    default List<T> listByIds(Collection<? extends Serializable> idList); // 调用 BaseMapper 的 selectBatchIds 方法,批量查询数据。
    default List<T> listByMap(Map<String, Object> columnMap); // 调用 BaseMapper 的 selectByMap 方法,根据表字段条件查询
    default T getOne(Wrapper<T> queryWrapper); // 返回一条记录(实体类保存)。
    Map<String, Object> getMap(Wrapper<T> queryWrapper); // 返回一条记录(map 保存)。
    default int count(Wrapper<T> queryWrapper); // 根据条件返回 记录数。
    default List<T> list(); // 返回所有数据。
    default List<T> list(Wrapper<T> queryWrapper); // 调用 BaseMapper 的 selectList 方法,查询所有记录(返回 entity 集合)。
    default List<Map<String, Object>> listMaps(Wrapper<T> queryWrapper); // 调用 BaseMapper 的 selectMaps 方法,查询所有记录(返回 map 集合)。
    default List<Object> listObjs(); // 返回全部记录,但只返回第一个字段的值。
    default <E extends IPage<T>> E page(E page, Wrapper<T> queryWrapper); // 调用 BaseMapper 的 selectPage 方法,分页查询
    default <E extends IPage<Map<String, Object>>> E pageMaps(E page, Wrapper<T> queryWrapper); // 调用 BaseMapper 的 selectMapsPage 方法,分页查询
注:
    get 用于返回一条记录。
    list 用于返回多条记录。
    count 用于返回记录总数。
    page 用于分页查询。
    
【链式调用:】
    default QueryChainWrapper<T> query(); // 普通链式查询
    default LambdaQueryChainWrapper<T> lambdaQuery(); // 支持 Lambda 表达式的修改
    default UpdateChainWrapper<T> update(); // 普通链式修改
    default LambdaUpdateChainWrapper<T> lambdaUpdate(); // 支持 Lambda 表达式的修改
注:
    query 表示查询
    update 表示修改
    Lambda 表示内部支持 Lambda 写法。
形如:
    query().eq("column", value).one();
    lambdaQuery().eq(Entity::getId, value).list();
    update().eq("column", value).remove();
    lambdaUpdate().eq(Entity::getId, value).update(entity);
复制代码

插入一条记录

 default boolean save(T entity);
复制代码
@Test
public void save_T(){
    Student stu=new Student ();
    stu.setName ("李清照");
    stu.setAge (21);
    stu.setEmail ("ssm@163.com");
    // 调用 BaseMapper 的 insert 方法,用于添加一条数据。
    boolean save = iStudentService.save (stu);
    System.out.println (save);
}

/**
 * ==>  Preparing: INSERT INTO student ( name, age, email ) VALUES ( ?, ?, ? )
 * ==> Parameters: 李清照(String), 21(Integer), ssm@163.com(String)
 * <==    Updates: 1
 */
复制代码

插入多条数据

boolean saveBatch(Collection<T> entityList, int batchSize);
复制代码
@Test
public void saveBatch(){
    List<Student> students = new ArrayList<>();
    students.add (new Student ("刘咏",22,"123@123.com"));
    students.add (new Student ("刘咏",22,"234@123.com"));
    students.add (new Student ("刘咏",22,"345@123.com"));
    students.add (new Student ("刘咏",22,"456@123.com"));
    // entityList 表示实体对象集合 
    // batchSize 表示一次批量插入的数据量,默认为 1000
    boolean b = iStudentService.saveBatch (students);
    System.out.println (b);
}

/*
 * ==>  Preparing: INSERT INTO student ( name, age, email ) VALUES ( ?, ?, ? )
 * ==> Parameters: 刘咏(String), 22(Integer), 123@123.com(String)
 * ==> Parameters: 刘咏(String), 22(Integer), 234@123.com(String)
 * ==> Parameters: 刘咏(String), 22(Integer), 345@123.com(String)
 * ==> Parameters: 刘咏(String), 22(Integer), 456@123.com(String)
 */
复制代码

根据主键删除数据

// 调用 BaseMapper 的 deleteById 方法,根据 id 删除数据。
default boolean removeById(Serializable id); 
复制代码
@Test
public void removeById_T(){
    // 调用 BaseMapper 的 deleteById 方法,根据 id 删除数据。
    boolean start = iStudentService.removeById (1062);
    System.out.println (start);
}
复制代码

根据map定义条件删除记录

default boolean removeByMap(Map<String, Object> columnMap);
复制代码
@Test
public void removeByMap_T(){
    boolean b = iStudentService.removeByMap (
        // 删除name = 刘咏 , id = 1059 的记录
        // ImmutableMap 生成的Map为不可变Map
        ImmutableMap.of ("name" , "刘咏" , "id" , "1059")
    );
    System.out.println (b);
}
    
/*
 * ==>  Preparing: DELETE FROM student WHERE name = ? AND id = ?
 * ==> Parameters: 刘咏(String), 1059(String)
 * <==    Updates: 1
 */
复制代码

删除多条数据

default boolean removeByIds(Collection<? extends Serializable> idList); 
复制代码
@Test
public void removeByIds_T(){
    // 用 BaseMapper 的 deleteBatchIds 方法, 进行批量删除。
    boolean start = iStudentService.removeByIds (Stream.of (1065,1064,1063,1062).collect(Collectors.toList()));
    System.out.println (start);
}

/*
 * ==>  Preparing: DELETE FROM student WHERE id IN ( ? , ? , ? , ? )
 * ==> Parameters: 1065(Integer), 1064(Integer), 1063(Integer), 1062(Integer)
 * <==    Updates: 3
 */
复制代码

根据自定义条件删除数据

default boolean remove(Wrapper<T> queryWrapper);
复制代码
@Test
public void remove_T(){
    boolean start = iStudentService.remove (new QueryWrapper<Student> ().eq ("id" , 1049));
    System.out.println (start);
}

/**
 * ==>  Preparing: DELETE FROM student WHERE (id = ?)
 * ==> Parameters: 1049(Integer)
 * <==    Updates: 1
 */
复制代码

根据 主键 修改记录

default boolean updateById(T entity);
复制代码
@Test
public void updateById_T(){
    Student student = new Student ();
    student.setId (1024L);
    student.setName ("09:26修改测试");
    // 调用 BaseMapper 的 updateById 方法,根据 ID 选择修改。
    boolean b = iStudentService.updateById (student);
    System.out.println (b);
/*
 * ==>  Preparing: UPDATE student SET name=? WHERE id=?
 * ==> Parameters: 09:26修改测试(String), 1024(Long)
 * <==    Updates: 1
 */
}
复制代码

修改多条数据

boolean updateBatchById(Collection<T> entityList, int batchSize); 
复制代码
 // 批量更新数据
	@Test
	public void updateBatchById_T(){

		Student student = new Student ();
		student.setId (1025L);
		student.setEmail ("369@124");
		student.setAge (16);
		student.setName ("updateBatchById_T() 修改测试");

		Student student1 = new Student ();
		student1.setId (1026L);
		student1.setEmail ("369@124");
		student1.setAge (16);
		student1.setName ("updateBatchById_T() 修改测试");

		Student student2 = new Student ();
		student2.setId (1027L);
		student2.setEmail ("369@124");
		student2.setAge (16);
		student2.setName ("updateBatchById_T() 修改测试");

		List<Student> students = new ArrayList<> ();
		students.add(student2);
		students.add (student1);
		students.add (student);

		boolean b = iStudentService.updateBatchById (students);
		System.out.println (b);
	}

/*
 * ==>  Preparing: UPDATE student SET name=?, age=?, email=? WHERE id=?
 * ==> Parameters: updateBatchById_T() 修改测试(String), 16(Integer), 369@124(String), 1027(Long)
 * ==> Parameters: updateBatchById_T() 修改测试(String), 16(Integer), 369@124(String), 1026(Long)
 * ==> Parameters: updateBatchById_T() 修改测试(String), 16(Integer), 369@124(String), 1025(Long)
 */
复制代码

根据自定义条件修改

default boolean update(T entity, Wrapper<T> updateWrapper);
复制代码
// 调用 BaseMapper 的 update 方法,根据 updateWrapper 条件修改实体对象。
@Test
public void update(){

    Student student = new Student ();
    student.setId (1027L);
    student.setEmail ("369@124");
    student.setAge (16);
    student.setName ("update() 修改测试");

    boolean b = iStudentService.update (student , new UpdateWrapper<Student> ().eq ("id" , "1027"));
    System.out.println (b);
}


/*
 * ==>  Preparing: UPDATE student SET name=?, age=?, email=? WHERE (id = ?)
 * ==> Parameters: update() 修改测试(String), 16(Integer), 369@124(String), 1027(String)
 * <==    Updates: 1
 */
复制代码

根据主键查询

default T getById(Serializable id);
复制代码
@Test
public void getById_T(){
    System.out.println (iStudentService.getById (1034L));
}

/*
 * ==>  Preparing: SELECT id,name,age,email FROM student WHERE id=?
 * ==> Parameters: 1034(Long)
 * <==    Columns: id, name, age, email
 * <==        Row: 1034, 白居易7, 19, 1623@163.com
 * <==      Total: 1
 */
复制代码

根据主键批量查询

paramType :List

return :List

default List<T> listByIds(Collection<? extends Serializable> idList);
复制代码
// 调用 BaseMapper 的 selectBatchIds 方法,批量查询数据。
@Test
public void listByIds_T(){
    iStudentService.listByIds (Stream.of (1034L,1035L,1036L).collect(Collectors.toList()))
        .forEach (System.out :: println);
}

/**
 * ==>  Preparing: SELECT id,name,age,email FROM student WHERE id IN ( ? , ? , ? )
 * ==> Parameters: 1034(Long), 1035(Long), 1036(Long)
 * <==    Columns: id, name, age, email
 * <==        Row: 1034, 白居易7, 19, 1623@163.com
 * <==        Row: 1035, 白居易8, 19, 1623@163.com
 * <==        Row: 1036, 白居易9, 19, 1623@163.com
 * <==      Total: 3
 * Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@554188ac]
 * Student [Hash = 240195991, id=1034, name=白居易7, age=19, email=1623@163.com, serialVersionUID=1]
 * Student [Hash = 240226743, id=1035, name=白居易8, age=19, email=1623@163.com, serialVersionUID=1]
 * Student [Hash = 240257495, id=1036, name=白居易9, age=19, email=1623@163.com, serialVersionUID=1]
 */
复制代码

根据Map条件查询

paramType :Map

return :List

default List<T> listByMap(Map<String, Object> columnMap);
复制代码
// 调用 BaseMapper 的 selectByMap 方法,根据表字段条件查询
@Test
public void listByMap_T(){
    iStudentService.listByMap (
        ImmutableMap.of ("name","柳宗元","age","18")
    ).forEach (System.out :: println);
}

/**
 * ==>  Preparing: SELECT id,name,age,email FROM student WHERE name = ? AND age = ?
 * ==> Parameters: 柳宗元(String), 18(String)
 * <==    Columns: id, name, age, email
 * <==        Row: 1007, 柳宗元, 18, 165@163.com
 * <==        Row: 1008, 柳宗元, 18, 165@163.com
 * <==        Row: 1009, 柳宗元, 18, 165@163.com
 *          ......
 * <==      Total: 17
 * Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@553da911]
 * Student [Hash = 374796304, id=1007, name=柳宗元, age=18, email=165@163.com, serialVersionUID=1]
 * Student [Hash = 374826095, id=1008, name=柳宗元, age=18, email=165@163.com, serialVersionUID=1]
 * Student [Hash = 374855886, id=1009, name=柳宗元, age=18, email=165@163.com, serialVersionUID=1]
 */
复制代码

查找首条记录

default T getOne(Wrapper<T> queryWrapper); 
public T getOne(Wrapper<T> queryWrapper, boolean throwEx);

//即getOne方法默认throwEx参数为true
default T getOne(Wrapper<T> queryWrapper) {
    return this.getOne(queryWrapper, true);
}

//由返回值可知,
//当传入布尔值为true时 , 调用baseMapper.selectOne()方法。即当返回记录数不为 1 时,抛出异常。
//当传入布尔值为false时, 则取首条记录
public T getOne(Wrapper<T> queryWrapper, boolean throwEx) {
    return throwEx ? this.baseMapper.selectOne(queryWrapper) : SqlHelper.getObject(this.log, this.baseMapper.selectList(queryWrapper));
}
复制代码
@Test
public void getOne_T(){
    //返回数据不唯一,抛出异常
    System.out.println (iStudentService.getOne (new QueryWrapper<Student> ().likeRight ("name" , "白居易") ));
/**
  *org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.TooManyResultsException: Expected one result  (or null) to be returned by selectOne(), but found: 28
 */
}

@Test
public void getOne_T(){
    
    System.out.println (iStudentService.getOne (new QueryWrapper<Student> ().likeRight ("name" , "白居易") , false));
 
/**
 * ==>  Preparing: SELECT id,name,age,email FROM student WHERE (name LIKE ?)
 * ==> Parameters: 白居易%(String)
 * <==    Columns: id, name, age, email
 * <==        Row: 1028, 白居易1, 19, 1623@163.com
 *          .....
 * <==        Row: 1055, 白居易28, 19, 1623@163.com
 * <==        Row: 1056, 白居易29, 19, 1623@163.com
 * <==      Total: 28
 * Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@340d6d89]
 * Warn: execute Method There are  28 results.
 * Student [Hash = 240011479, id=1028, name=白居易1, age=19, email=1623@163.com, serialVersionUID=1]
 */
    
}
复制代码

查找首条记录 Map

 Map<String, Object> getMap(Wrapper<T> queryWrapper); 
复制代码
// 返回一条记录(map 保存)。
@Test
public void getMap_T(){
    iStudentService.getMap (new QueryWrapper<Student> ().likeRight ("name" , "白居易")).forEach (
        (key,value)->{
            System.out.println (key+"---"+value);
        }
    );
}


/**
 * ==>  Preparing: SELECT id,name,age,email FROM student WHERE (name LIKE ?)
 * ==> Parameters: 白居易%(String)
 * <==    Columns: id, name, age, email
 * <==        Row: 1028, 白居易1, 19, 1623@163.com
 * <==        Row: 1029, 白居易2, 19, 1623@163.com
 * <==        Row: 1030, 白居易修改测试, 19, 1623@163.com
 *          ......
 * <==      Total: 28
 * Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@43cb5f38]
 * Warn: execute Method There are  28 results.
 * name---白居易1
 * id---1028
 * age---19
 * email---1623@163.com
 */
复制代码

返回记录总数(Count)

default int count(Wrapper<T> queryWrapper); 
复制代码
@Test
public void count_T(){
    int count = iStudentService.count (new QueryWrapper<Student> ().likeRight ("name" , "白居易"));
    System.out.println (count);
}

/**
 * ==>  Preparing: SELECT COUNT( * ) FROM student WHERE (name LIKE ?)
 * ==> Parameters: 白居易%(String)
 * <==    Columns: COUNT( * )
 * <==        Row: 28
 * <==      Total: 1
 * Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2cca611f]
 * 28
 */
复制代码

返回所有记录 List

default List<T> list();
复制代码
@Test
public void List_T(){
    iStudentService.list ().forEach (System.out :: println);
}

/**
 * ==>  Preparing: SELECT id,name,age,email FROM student
 * ==> Parameters: 
 * <==    Columns: id, name, age, email
 */
复制代码

有条件的查询记录 List

 default List<T> list(Wrapper<T> queryWrapper);
复制代码
//调用 BaseMapper 的 selectList 方法,查询所有记录(返回 entity 集合)。
@Test
public void Lists_T(){
    iStudentService.list (new QueryWrapper<Student> ().likeRight ("name" , "白居易"))
        .forEach (System.out :: println);
}

/**
 * ==>  Preparing: SELECT id,name,age,email FROM student WHERE (name LIKE ?)
 * ==> Parameters: 白居易%(String)
 * <==    Columns: id, name, age, email
 * <==        Row: 1028, 白居易1, 19, 1623@163.com
 * <==        Row: 1029, 白居易2, 19, 1623@163.com
 *          ......
 * <==      Total: 28
 */
复制代码

返回所有记录 Map

default List<Map<String, Object>> listMaps(Wrapper<T> queryWrapper); 
复制代码
// 调用 BaseMapper 的 selectMaps 方法,查询所有记录(返回 map 集合)。
@Test
public void listMaps_T(){
    iStudentService.listMaps (new QueryWrapper<Student> ().likeRight ("name" , "白居易"))
        .forEach (item->item.forEach ((key,value)->{
            System.out.println (key+" --- "+value);
        }));
}

/**
 * ==>  Preparing: SELECT id,name,age,email FROM student WHERE (name LIKE ?)
 * ==> Parameters: 白居易%(String)
 * <==    Columns: id, name, age, email
 * <==        Row: 1028, 白居易1, 19, 1623@163.com
 * <==        Row: 1029, 白居易2, 19, 1623@163.com
 * <==        Row: 1030, 白居易修改测试, 19, 1623@163.com
 *          ......
 * <==      Total: 28
 * name --- 白居易1
 * id --- 1028
 * age --- 19
 * email --- 1623@163.com
 * name --- 白居易2
 * id --- 1029
 * age --- 19
 * email --- 1623@163.com
 * name --- 白居易修改测试
 * id --- 1030
 * age --- 19
 * email --- 1623@163.com
 */
复制代码

获取所有首字段的值 List

default List<Object> listObjs();
default List<Object> listObjs(Function<? super Object, Object>);
default List<Object> listObjs(Wrapper<Student>);
default List<Object> listObjs(Wrapper<Student>, Function<? super Object, Object>);
复制代码
// 返回全部记录,但只返回第一个字段的值。
@Test
public void listObjs_T(){
    iStudentService.listObjs (new QueryWrapper<Student> ().likeRight ("name" , "白居易"))
        .forEach (System.out :: println);
}
/**
 * ==>  Preparing: SELECT id,name,age,email FROM student WHERE (name LIKE ?)
 * ==> Parameters: 白居易%(String)
 * <==    Columns: id, name, age, email
 * <==        Row: 1028, 白居易1, 19, 1623@163.com
 * <==        Row: 1029, 白居易2, 19, 1623@163.com
 * <==        Row: 1030, 白居易修改测试, 19, 1623@163.com
 *          .....
 * <==      Total: 28
 * 
 * 1028
 * 1029
 * .....
 */
复制代码

分页查询 IPage

default <E extends IPage<T>> E page(E page, Wrapper<T> queryWrapper);
复制代码
 // 调用 BaseMapper 的 selectPage 方法,分页查询
复制代码

分页查询 IPage<Map<String,Object>>

default <E extends IPage<Map<String, Object>>> E pageMaps(E page, Wrapper<T> queryWrapper); 
复制代码
// 调用 BaseMapper 的 selectMapsPage 方法,分页查询
复制代码

添加或修改

有则修改,无则新增

boolean saveOrUpdate(T entity);

public boolean saveOrUpdate(T entity) {
    if (null == entity) {
        return false;
    } else {
        TableInfo tableInfo = TableInfoHelper.getTableInfo(this.entityClass);
        Assert.notNull(tableInfo, "error: can not execute. because can not find cache of TableInfo for entity!", new Object[0]);
        String keyProperty = tableInfo.getKeyProperty();
        Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!", new Object[0]);
        Object idVal = ReflectionKit.getFieldValue(entity, tableInfo.getKeyProperty());
        
        return !StringUtils.checkValNull(idVal) && !Objects.isNull(this.getById((Serializable)idVal)) ? this.updateById(entity) : this.save(entity);
        
    }
}
复制代码
@Test
public void saveOrUpdate_T(){
    iStudentService.saveOrUpdate (new Student ("saveOrUpdate_T()",13,"13@13"));
}
/**
 * ==>  Preparing: INSERT INTO student ( name, age, email ) VALUES ( ?, ?, ? )
 * ==> Parameters: saveOrUpdate_T()(String), 13(Integer), 13@13(String)
 * <==    Updates: 1
 */
复制代码

先根据条件尝试更新,然后再执行 saveOrUpdate 操作

 default boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper); // 先根据条件尝试更新,然后再执行 saveOrUpdate 操作
复制代码
@Test
public void saveOrUpdate_T2(){
    iStudentService.saveOrUpdate (new Student ("saveOrUpdate_T()",13,"13@13"),
                                  new UpdateWrapper<Student> ().eq ("age",14).likeRight ("name","白居易"));
}

/**
 * ==>  Preparing: UPDATE student SET name=?, age=?, email=? WHERE (age = ? AND name LIKE ?)
 * ==> Parameters: saveOrUpdate_T()(String), 13(Integer), 13@13(String), 14(Integer), 白居易%(String)
 * <==    Updates: 1
 */
复制代码

批量插入或修改数据

public boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize);

public boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize) {
    TableInfo tableInfo = TableInfoHelper.getTableInfo(this.entityClass);
    Assert.notNull(tableInfo, "error: can not execute. because can not find cache of TableInfo for entity!", new Object[0]);
    String keyProperty = tableInfo.getKeyProperty();
    Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!", new Object[0]);
    return SqlHelper.saveOrUpdateBatch(this.entityClass, this.mapperClass, this.log, entityList, batchSize, (sqlSession, entity) -> {
        Object idVal = ReflectionKit.getFieldValue(entity, keyProperty);
        return StringUtils.checkValNull(idVal) || CollectionUtils.isEmpty(sqlSession.selectList(this.getSqlStatement(SqlMethod.SELECT_BY_ID), entity));
    }, (sqlSession, entity) -> {
        ParamMap<T> param = new ParamMap();
        param.put("et", entity);
        sqlSession.update(this.getSqlStatement(SqlMethod.UPDATE_BY_ID), param);
    });
}
复制代码
@Test
public void saveOrUpdateBatch_T(){

    Student student = new Student ();
    student.setId (1025L);
    student.setEmail ("369@124");
    student.setAge (16);
    student.setName ("saveOrUpdateBatch_T() 修改测试");

    Student student1 = new Student ();
    student1.setId (1026L);
    student1.setEmail ("369@124");
    student1.setAge (16);
    student1.setName ("saveOrUpdateBatch_T() 修改测试");

    Student student2 = new Student ();
    student2.setId (1200L);
    student2.setEmail ("369@124");
    student2.setAge (16);
    student2.setName ("saveOrUpdateBatch_T() 修改测试");


    Student student4 = new Student ();
    student2.setEmail ("369@124");
    student2.setAge (16);
    student2.setName ("saveOrUpdateBatch_T() 修改测试");

    List<Student> students = new ArrayList<> ();
    students.add(student2);
    students.add (student1);
    students.add (student);
    
    //添加student4后报错,可能id不能为null?但是saveOrUpdate中为空则执行插入
    //students.add (student4);

    boolean b = iStudentService.saveOrUpdateBatch (students);
}

/**
 * ==>  Preparing: SELECT id,name,age,email FROM student WHERE id=?
 * ==> Parameters: 1200(Long)
 * <==      Total: 0
 * ==>  Preparing: INSERT INTO student ( name, age, email ) VALUES ( ?, ?, ? )
 * ==> Parameters: saveOrUpdateBatch_T() 修改测试(String), 16(Integer), 369@124(String)
 * ==>  Preparing: SELECT id,name,age,email FROM student WHERE id=?
 * ==> Parameters: 1026(Long)
 * <==    Columns: id, name, age, email
 * <==        Row: 1026, saveOrUpdateBatch_T() 修改测试, 16, 369@124
 * <==      Total: 1
 * ==>  Preparing: UPDATE student SET name=?, age=?, email=? WHERE id=?
 * ==> Parameters: saveOrUpdateBatch_T() 修改测试(String), 16(Integer), 369@124(String), 1026(Long)
 * ==>  Preparing: SELECT id,name,age,email FROM student WHERE id=?
 * ==> Parameters: 1025(Long)
 * <==    Columns: id, name, age, email
 * <==        Row: 1025, saveOrUpdateBatch_T() 修改测试, 16, 369@124
 * <==      Total: 1
 * ==>  Preparing: UPDATE student SET name=?, age=?, email=? WHERE id=?
 * ==> Parameters: saveOrUpdateBatch_T() 修改测试(String), 16(Integer), 369@124(String), 1025(Long)
 */
复制代码

8.5 链式调用

default QueryChainWrapper<T> query(); // 普通链式查询
default LambdaQueryChainWrapper<T> lambdaQuery(); // 支持 Lambda 表达式的修改
default UpdateChainWrapper<T> update(); // 普通链式修改
default LambdaUpdateChainWrapper<T> lambdaUpdate(); // 支持 Lambda 表达式的修改
复制代码
query().eq("column", value).one();
lambdaQuery().eq(Entity::getId, value).list();
update().eq("column", value).remove();
lambdaUpdate().eq(Entity::getId, value).update(entity);
复制代码

8.6 各操作对应SQL语句参考

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.baomidou.mybatisplus.core.enums;

public enum SqlMethod {
    INSERT_ONE("insert", "插入一条数据(选择字段插入)", "<script>\nINSERT INTO %s %s VALUES %s\n</script>"),
    UPSERT_ONE("upsert", "Phoenix插入一条数据(选择字段插入)", "<script>\nUPSERT INTO %s %s VALUES %s\n</script>"),
    DELETE_BY_ID("deleteById", "根据ID 删除一条数据", "<script>\nDELETE FROM %s WHERE %s=#{%s}\n</script>"),
    DELETE_BY_MAP("deleteByMap", "根据columnMap 条件删除记录", "<script>\nDELETE FROM %s %s\n</script>"),
    DELETE("delete", "根据 entity 条件删除记录", "<script>\nDELETE FROM %s %s %s\n</script>"),
    DELETE_BATCH_BY_IDS("deleteBatchIds", "根据ID集合,批量删除数据", "<script>\nDELETE FROM %s WHERE %s IN (%s)\n</script>"),
    LOGIC_DELETE_BY_ID("deleteById", "根据ID 逻辑删除一条数据", "<script>\nUPDATE %s %s WHERE %s=#{%s} %s\n</script>"),
    LOGIC_DELETE_BY_MAP("deleteByMap", "根据columnMap 条件逻辑删除记录", "<script>\nUPDATE %s %s %s\n</script>"),
    LOGIC_DELETE("delete", "根据 entity 条件逻辑删除记录", "<script>\nUPDATE %s %s %s %s\n</script>"),
    LOGIC_DELETE_BATCH_BY_IDS("deleteBatchIds", "根据ID集合,批量逻辑删除数据", "<script>\nUPDATE %s %s WHERE %s IN (%s) %s\n</script>"),
    UPDATE_BY_ID("updateById", "根据ID 选择修改数据", "<script>\nUPDATE %s %s WHERE %s=#{%s} %s\n</script>"),
    UPDATE("update", "根据 whereEntity 条件,更新记录", "<script>\nUPDATE %s %s %s %s\n</script>"),
    LOGIC_UPDATE_BY_ID("updateById", "根据ID 修改数据", "<script>\nUPDATE %s %s WHERE %s=#{%s} %s\n</script>"),
    SELECT_BY_ID("selectById", "根据ID 查询一条数据", "SELECT %s FROM %s WHERE %s=#{%s} %s"),
    SELECT_BY_MAP("selectByMap", "根据columnMap 查询一条数据", "<script>SELECT %s FROM %s %s\n</script>"),
    SELECT_BATCH_BY_IDS("selectBatchIds", "根据ID集合,批量查询数据", "<script>SELECT %s FROM %s WHERE %s IN (%s) %s</script>"),
    SELECT_ONE("selectOne", "查询满足条件一条数据", "<script>%s SELECT %s FROM %s %s %s\n</script>"),
    SELECT_COUNT("selectCount", "查询满足条件总记录数", "<script>%s SELECT COUNT(%s) FROM %s %s %s\n</script>"),
    SELECT_LIST("selectList", "查询满足条件所有数据", "<script>%s SELECT %s FROM %s %s %s\n</script>"),
    SELECT_PAGE("selectPage", "查询满足条件所有数据(并翻页)", "<script>%s SELECT %s FROM %s %s %s\n</script>"),
    SELECT_MAPS("selectMaps", "查询满足条件所有数据", "<script>%s SELECT %s FROM %s %s %s\n</script>"),
    SELECT_MAPS_PAGE("selectMapsPage", "查询满足条件所有数据(并翻页)", "<script>\n %s SELECT %s FROM %s %s %s\n</script>"),
    SELECT_OBJS("selectObjs", "查询满足条件所有数据", "<script>%s SELECT %s FROM %s %s %s\n</script>");

    private final String method;
    private final String desc;
    private final String sql;

    private SqlMethod(String method, String desc, String sql) {
        this.method = method;
        this.desc = desc;
        this.sql = sql;
    }

    public String getMethod() {
        return this.method;
    }

    public String getDesc() {
        return this.desc;
    }

    public String getSql() {
        return this.sql;
    }
}
复制代码

注:数据库引入数据

/*
 Navicat Premium Data Transfer

 Source Server         : imooc
 Source Server Type    : MySQL
 Source Server Version : 80021
 Source Host           : localhost:3306
 Source Schema         : mybatisplus_demo

 Target Server Type    : MySQL
 Target Server Version : 80021
 File Encoding         : 65001

 Date: 23/06/2022 11:34:24
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for student
-- ----------------------------
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student`  (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID,学号',
  `name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '姓名',
  `age` int NULL DEFAULT NULL COMMENT '年龄',
  `email` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '邮箱',
  PRIMARY KEY (`id`) USING BTREE,
  INDEX `id`(`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1063 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of student
-- ----------------------------
INSERT INTO `student` VALUES (1002, 'Jack', 20, 'test2@baomidou.com');
INSERT INTO `student` VALUES (1003, 'Tom', 28, 'test3@baomidou.com');
INSERT INTO `student` VALUES (1004, 'Sandy', 21, 'test4@baomidou.com');
INSERT INTO `student` VALUES (1005, 'Billie', 24, 'test5@baomidou.com');
INSERT INTO `student` VALUES (1007, '柳宗元', 18, '165@163.com');
INSERT INTO `student` VALUES (1008, '柳宗元', 18, '165@163.com');
INSERT INTO `student` VALUES (1009, '柳宗元', 18, '165@163.com');
INSERT INTO `student` VALUES (1010, '柳宗元', 18, '165@163.com');
INSERT INTO `student` VALUES (1011, '柳宗元', 18, '165@163.com');
INSERT INTO `student` VALUES (1012, '柳宗元', 18, '165@163.com');
INSERT INTO `student` VALUES (1013, '柳宗元', 18, '165@163.com');
INSERT INTO `student` VALUES (1014, '柳宗元', 18, '165@163.com');
INSERT INTO `student` VALUES (1015, '柳宗元', 18, '165@163.com');
INSERT INTO `student` VALUES (1016, '柳宗元', 18, '165@163.com');
INSERT INTO `student` VALUES (1017, '柳宗元', 18, '165@163.com');
INSERT INTO `student` VALUES (1018, '柳宗元', 18, '165@163.com');
INSERT INTO `student` VALUES (1019, '柳宗元', 18, '165@163.com');
INSERT INTO `student` VALUES (1020, '柳宗元', 18, '165@163.com');
INSERT INTO `student` VALUES (1021, '柳宗元', 18, '165@163.com');
INSERT INTO `student` VALUES (1022, '柳宗元', 18, '165@163.com');
INSERT INTO `student` VALUES (1023, '柳宗元', 18, '165@163.com');
INSERT INTO `student` VALUES (1024, '09:26修改测试', 18, '165@163.com');
INSERT INTO `student` VALUES (1025, 'saveOrUpdateBatch_T() 修改测试', 16, '369@124');
INSERT INTO `student` VALUES (1026, 'saveOrUpdateBatch_T() 修改测试', 16, '369@124');
INSERT INTO `student` VALUES (1027, 'saveOrUpdateBatch_T() 修改测试', 16, '369@124');
INSERT INTO `student` VALUES (1028, '白居易1', 19, '1623@163.com');
INSERT INTO `student` VALUES (1029, '白居易2', 19, '1623@163.com');
INSERT INTO `student` VALUES (1030, '白居易修改测试', 19, '1623@163.com');
INSERT INTO `student` VALUES (1031, 'saveOrUpdate_T()', 13, '13@13');
INSERT INTO `student` VALUES (1032, '白居易5', 19, '1623@163.com');
INSERT INTO `student` VALUES (1033, '白居易6', 19, '1623@163.com');
INSERT INTO `student` VALUES (1034, '白居易7', 19, '1623@163.com');
INSERT INTO `student` VALUES (1035, '白居易8', 19, '1623@163.com');
INSERT INTO `student` VALUES (1036, '白居易9', 19, '1623@163.com');
INSERT INTO `student` VALUES (1037, '白居易10', 19, '1623@163.com');
INSERT INTO `student` VALUES (1038, '白居易11', 19, '1623@163.com');
INSERT INTO `student` VALUES (1039, '白居易12', 19, '1623@163.com');
INSERT INTO `student` VALUES (1040, '白居易13', 19, '1623@163.com');
INSERT INTO `student` VALUES (1041, '白居易14', 19, '1623@163.com');
INSERT INTO `student` VALUES (1042, '白居易15', 19, '1623@163.com');
INSERT INTO `student` VALUES (1043, '白居易16', 19, '1623@163.com');
INSERT INTO `student` VALUES (1044, '白居易17', 19, '1623@163.com');
INSERT INTO `student` VALUES (1045, '白居易18', 19, '1623@163.com');
INSERT INTO `student` VALUES (1046, '白居易19', 19, '1623@163.com');
INSERT INTO `student` VALUES (1047, '白居易20', 19, '1623@163.com');
INSERT INTO `student` VALUES (1048, '白居易21', 19, '1623@163.com');
INSERT INTO `student` VALUES (1050, '白居易23', 19, '1623@163.com');
INSERT INTO `student` VALUES (1051, '白居易24', 19, '1623@163.com');
INSERT INTO `student` VALUES (1052, '白居易25', 19, '1623@163.com');
INSERT INTO `student` VALUES (1053, '白居易26', 19, '1623@163.com');
INSERT INTO `student` VALUES (1054, '白居易27', 19, '1623@163.com');
INSERT INTO `student` VALUES (1055, '白居易28', 19, '1623@163.com');
INSERT INTO `student` VALUES (1056, '白居易29', 19, '1623@163.com');
INSERT INTO `student` VALUES (1057, '李清照', 21, 'ssm@163.com');
INSERT INTO `student` VALUES (1058, '李清照', 21, 'ssm@163.com');
INSERT INTO `student` VALUES (1066, '刘咏', 22, '456@123.com');
INSERT INTO `student` VALUES (1067, '李清照', 21, 'ssm@163.com');
INSERT INTO `student` VALUES (1068, '刘咏', 22, '123@123.com');
INSERT INTO `student` VALUES (1069, '刘咏', 22, '234@123.com');
INSERT INTO `student` VALUES (1070, '刘咏', 22, '345@123.com');
INSERT INTO `student` VALUES (1071, '刘咏', 22, '456@123.com');
INSERT INTO `student` VALUES (1072, 'saveOrUpdate_T()', 13, '13@13');
INSERT INTO `student` VALUES (1073, 'saveOrUpdate_T()', 13, '13@13');
INSERT INTO `student` VALUES (1075, 'saveOrUpdateBatch_T() 修改测试', 16, '369@124');

SET FOREIGN_KEY_CHECKS = 1;
复制代码
举报
评论 0