Mybatis-Plus一文详解BaseMapper和Service 使用

news2024/11/15 9:13:16

Mybatis-Plus简介

MyBatis-Plus (opens new window)(简称 MP)是一个MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
特性:

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
  • 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
  • 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
  • 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
  • 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
  • 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
  • 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
  • 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
  • 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
  • 内置性能分析插件:可输出 SQL 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
  • 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作

MyBatis Plus基础使用-helloworld

1:导包

<?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>
    <groupId>com.example</groupId>
    <artifactId>mybatis-plus</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>mybatis-plus</name>
    <description>mybatis-plus</description>
    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring-boot.version>2.6.13</spring-boot.version>
    </properties>
    <dependencies>
        <!--springboot依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!--测试场景-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!--mybatis plus场景-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.1</version>
        </dependency>
        <!-- mybatis plus 代码生成器引擎依赖-->
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity</artifactId>
            <version>1.7</version>
        </dependency>
        <!-- mybatis plus 代码生成器依赖 -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.5.1</version>
        </dependency>
        <dependency>
            <groupId>com.github.yulichang</groupId>
            <artifactId>mybatis-plus-join</artifactId>
            <version>1.2.4</version>
        </dependency>
        <!--数据库-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.21</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
            <scope>provided</scope>
        </dependency>

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


    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>${spring-boot.version}</version>
                <configuration>
                    <mainClass>com.example.mybatisplus.MybatisPlusApplication</mainClass>
                    <skip>true</skip>
                </configuration>
                <executions>
                    <execution>
                        <id>repackage</id>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

2:配置application.yml

spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/table_name?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&autoReconnect=true&allowMultiQueries=true&serverTimezone=GMT%2B8&rewriteBatchedStatements=true&useSSL=true
    username: root
    password: 123456

mybatis-plus:
  mapper-locations: classpath:mapper/*.xml,classpath:mapper/*/*.xml
  #配置日志
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

3:mybatis-plus代码生成器


package com.example.mybatisplus.utils;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.engine.VelocityTemplateEngine;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class CodeGenerator {
 
    public static void main(String[] args){
        String url = "jdbc:mysql://127.0.0.1:3306/table_name?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull&autoReconnect=true&allowMultiQueries=true&serverTimezone=GMT%2B8&rewriteBatchedStatements=true&useSSL=true";
        String username = "root";
        String password = "123456";
        String outPath = System.getProperty("user.dir")  + "/src/main/java";//文件输出路径
        String outPathxml = System.getProperty("user.dir") + "/src/main/resources/mapper";//xml文件输出路径
        String parent = "com.example.mybatisplus";//父包的名称
        String moduleName = "";//模块名称

        String entity = "entity";//设置实体类文件名
        String mapper = "mapper";
        String service = "service";
        String serviceImpl = "service.impl";
        String controller = "controller";

        //表名
        List<String> tables = new ArrayList<>();
        tables.add("country_dic");
 
 
        FastAutoGenerator.create(url, username, password)
                //全局配置
                .globalConfig(builder -> {
                    builder.author("wkl") // 设置作者
//                            .enableSwagger() // 开启 swagger 模式
                            .fileOverride() // 覆盖已生成文件
                            .outputDir(outPath) // 指定输出目录
                            .disableOpenDir();// 生成后不打开目录
                })
 
                //包配置
                .packageConfig(builder -> {
                    builder.parent(parent) // 设置父包名
                            .moduleName(moduleName) // 设置父包模块名
                            .entity(entity)//设置实体类文件名
                            .mapper(mapper)
                            .service(service)
                            .serviceImpl(serviceImpl)
                            .controller(controller)
                            .pathInfo(Collections.singletonMap(OutputFile.mapperXml, outPathxml)); // 设置mapperXml生成路径
                })
                //策略配置
                .strategyConfig(builder -> {
                    builder.addInclude(tables) // 设置需要生成的表名
//                            .addTablePrefix("t_", "c_"); // 设置过滤表前缀
//                            .enableCapitalMode()// 开启大写命名
                            .entityBuilder()// 开启生成实体类
//                            .disableSerialVersionUID()// 禁用生成 serialVersionUID
                            .enableLombok()// 开启lombox模型
                            .enableTableFieldAnnotation() // 开启生成实体时生成字段注解
                            // 阿里巴巴开发规范之创建时间、更新时间 交由mybatis-plus处理,如若交给数据库处理,则取消此设置
                            // .addTableFills(new Column("create_time", FieldFill.INSERT), new Column("update_time", FieldFill.INSERT_UPDATE))

                            .mapperBuilder()//开启生成mapper
                            .superClass(BaseMapper.class)// 设置父类
                            .enableMapperAnnotation()// 开启mapper注解
                            .formatMapperFileName("%sMapper")//格式化mapper名称
                            .formatXmlFileName("%sMapper")//格式化xml名称
                            .enableBaseResultMap()// 生成通用的resultMap

                            .serviceBuilder()//开启生成service
                            .formatServiceFileName("%sService")//格式化service接口文件名称
                            .formatServiceImplFileName("%sServiceImpl")

                            .controllerBuilder()//开启生成controller
                            .enableHyphenStyle()//开启驼峰转连字符
                            .formatFileName("%sController")
                            .enableRestStyle();
                })
                .templateEngine(new VelocityTemplateEngine()) // 使用Freemarker引擎模板,默认的是Velocity引擎模板
                .execute();
    }
}

在这里插入图片描述

4:分析mybatis-plus文件结构

1:实体类

在这里插入图片描述

2:Service 接口

在这里插入图片描述

3:ServiceImpl 实现

在这里插入图片描述

4:Mapper 接口

在这里插入图片描述

5:Mapper xml

在这里插入图片描述

MyBatis Plus的使用

1:BaseMapper的查询

根据 ID 查询

T selectById(Serializable id);

根据 entity 条件,查询一条记录

T selectOne(@Param(Constants.WRAPPER) Wrapper queryWrapper);

userMapper.selectById(4L)

查询(根据ID 批量查询)

List selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);

userMapper.selectBatchIds(Arrays.asList(1L, 2L, 3L))

根据 entity 条件,查询全部记录

List selectList(@Param(Constants.WRAPPER) Wrapper queryWrapper);

userMapper.selectList(new QueryWrapper<User>().eq("age", 20)).forEach(System.out::println);

查询(根据 columnMap 条件)

List selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);

Map<String, Object> map = new HashMap<>();
map.put("name", "嘎嘎嘎");
map.put("age", 3);
userMapper.selectByMap(map).forEach(System.out::println);

==>  Preparing: SELECT id,name,age,email FROM user WHERE name = ? AND age = ?
==> Parameters: 嘎嘎嘎(String), 3(Integer)
<==    Columns: id, name, age, email
<==        Row: 4, 嘎嘎嘎, 3, gagaga@gaga.com
<==      Total: 1
User(id=4, name=嘎嘎嘎, age=3, email=gagaga@gaga.com)

根据 Wrapper 条件,查询全部记录

List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper queryWrapper);

userMapper.selectObjs(new QueryWrapper<User>().eq("age", 20)).forEach(System.out::println);

根据 Wrapper 条件,查询全部记录。注意: 只返回第一个字段的值

List selectObjs(@Param(Constants.WRAPPER) Wrapper queryWrapper);

userMapper.selectPage(new Page(1, 5), new QueryWrapper<User>().ne("id", 1L));

根据 entity 条件,查询全部记录(并翻页)

IPage selectPage(IPage page, @Param(Constants.WRAPPER) Wrapper queryWrapper);

userMapper.selectMapsPage(new Page(1, 5), new QueryWrapper<User>().ne("id", 1L));

根据 Wrapper 条件,查询全部记录(并翻页)

IPage<Map<String, Object>> selectMapsPage(IPage page, @Param(Constants.WRAPPER) Wrapper queryWrapper);

userMapper.selectMapsPage(new Page(1, 5), new QueryWrapper<User>().ne("id", 1L));

根据 Wrapper 条件,查询总记录数

Integer selectCount(@Param(Constants.WRAPPER) Wrapper queryWrapper);

System.out.println("结果:" + userMapper.selectCount(new QueryWrapper<User>().eq("id", 1L)));

==>  Preparing: SELECT COUNT( * ) FROM user WHERE (id = ?)
==> Parameters: 1(Long)
<==    Columns: COUNT( * )
<==        Row: 1
<==      Total: 1
结果:1

2:BaseMapper的新增

插入一条记录

int insert(T entity);

==>  Preparing: INSERT INTO user ( id, name, age, email ) VALUES ( ?, ?, ?, ? )
==> Parameters: 1583712489828356098(Long), Ami(String), 20(Integer), 999@mm.com(String)
<==    Updates: 1
结果:1
User(id=1583712489828356098, name=Ami, age=20, email=999@mm.com)

注:第一次用的小伙伴肯定很好奇,我没有给表主键设置自增,我也没给主键赋值,为何主键会有值呢?

MP默认使用雪花算法给主键赋值

3:BaseMapper的修改

mybatis-plus 在 serviceImpl 层可以直接使用 this.baseMapper.update 和 updateById ,
如果更新的字段值是null,这时候需更新为 null 的字段更新不成功。打印的 sql 也没有更新为 null 的字段。

原因:
Mybatis-Plus默认的更新策略设置的问题,Mybatis-Plus中FieldStrategy有三种策略:

  • IGNORED:忽略。不管有没有有设置属性,所有的字段都会设置到insert语句中,如果没设置值会更新为null;
  • NOT_NULL:非 NULL,默认策略。也就是忽略null的字段,不忽略"";
  • NOT_EMPTY:非空。为null,为空串的忽略,就是如果设置值为null,“”,不会插入数据库;

根据 whereWrapper 条件,更新记录

int update(@Param(Constants.ENTITY) T updateEntity, @Param(Constants.WRAPPER) Wrapper whereWrapper);

User user = new User();
user.setId(400L);
user.setName("咕咕咕");
user.setAge(16);
user.setEmail("gugugu@gugu.com");
System.out.println("结果:" + userMapper.update(user, 
                                             new UpdateWrapper<User>().eq("id", 4L)));

==>  Preparing: UPDATE user SET name=?, age=?, email=? WHERE (id = ?)
==> Parameters: 咕咕咕(String), 16(Integer), gugugu@gugu.com(String), 4(Long)
<==    Updates: 1
结果:1

根据 ID 修改

int updateById(@Param(Constants.ENTITY) T entity);

User user = new User();
user.setId(4L);
user.setName("嘎嘎嘎");
user.setAge(3);
user.setEmail("gagaga@gaga.com");
System.out.println("结果:" + userMapper.updateById(user));

==>  Preparing: UPDATE user SET name=?, age=?, email=? WHERE id=?
==> Parameters: 嘎嘎嘎(String), 3(Integer), gagaga@gaga.com(String), 4(Long)
<==    Updates: 1
结果:1

4:BaseMapper的删除

根据 entity 条件,删除记录

int delete(@Param(Constants.WRAPPER) Wrapper wrapper);

userMapper.delete(new QueryWrapper<User>().eq("id", 1L))

删除(根据ID 批量删除)

int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);

userMapper.deleteBatchIds(Arrays.asList(1L, 2L, 3L))

根据 ID 删除

int deleteById(Serializable id);

==>  Preparing: DELETE FROM user WHERE id=?
==> Parameters: 1583712489828356098(Long)
<==    Updates: 1
结果:1

根据 columnMap 条件,删除记录

int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);

Map<String, Object> map = new HashMap<>();
map.put("name", "张三");
map.put("age", 20);
System.out.println("结果:" + userMapper.deleteByMap(map));

==>  Preparing: DELETE FROM user WHERE name = ? AND age = ?
==> Parameters: 张三(String), 20(Integer)
<==    Updates: 0
结果:0

2:Wrapper查询

通过BaseMapper提供的一些方法我们可以完成一些基本的CRUD,但无法完成复杂条件的查询;对于复杂条件的查询,MyBatis Plus提供了Wrapper接口来处理;

Wrapper是MyBatis Plus提供的一个条件构造器,主要用于构建一系列条件,当Wrapper构建完成后,可以使用Wrapper中的条件进行查询、修改、删除等操作;

1:Wrapper的继承体系如下

在这里插入图片描述
Wrapper是条件构造抽象类,最顶端父类,其主要实现类有如下:

  • AbstractWrapper : 用于查询条件封装,生成 sql 的 where 条件
    • QueryWrapper : Query条件封装
    • UpdateWrapper : Update条件封装
    • AbstractLambdaWrapper : 使用Lambda语法
      • LambdaQueryWrapper :基于Lambda语法使用的查询Wrapper
      • LambdaUpdateWrapper : 基于Lambda语法使用的更新Wrapper

2:Wrapper的基本方法

AbstractWrapper是其他常用Wrapper的父类,用于生成 sql 的 where 条件
1)基本方法介绍
AbstractWrapper提供了很多公有的方法,其子类全部具备这些方法,方法列表如下

* 基本⽐较操作
方法名解释示例
eq等于 =eq(“name”, “老王”)—>name = ‘老王’
ne不等于 <>ne(“name”, “老王”)—>name <> ‘老王’
gt大于 >gt(“age”, 18)—>age > 18
ge大于等于 >=ge(“age”, 18)—>age >= 18
lt小于 <lt(“age”, 18)—>age < 18
le小于等于 <=le(“age”, 18)—>age <= 18
betweenbetween 值1 and 值2between(“age”, 18, 30)—>age between 18 and 30
notBetweennot between 值1 and 值2notBetween(“age”, 18, 30)—>age not between 18 and 30
* 模糊查询
方法名解释示例
likeLIKE ‘%值%’like(“name”, “王”)—>name like ‘%王%’
notLikeNOT LIKE ‘%值%’notLike(“name”, “王”)—>name not like ‘%王%’
likeLeftLIKE ‘%值’likeLeft(“name”, “王”)—>name like ‘%王’
likeRightLIKE ‘值%’likeRight(“name”, “王”)—>name like ‘王%’
* 分组排序
方法名解释示例
groupBy分组:GROUP BY 字段, …groupBy(“id”, “name”)—>group by id,name
orderByAsc排序:ORDER BY 字段, … ASCorderByAsc(“id”, “name”)—>order by id ASC,name ASC
orderByDesc排序:ORDER BY 字段, … DESCorderByDesc(“id”, “name”)—>order by id DESC,name DESC
orderBy排序:ORDER BY 字段, …orderBy(true, true, “id”, “name”)—>order by id ASC,name ASC
havingHAVING ( sql语句 )例1:having(“sum(age) > 10”) —>having sum(age) > 10,例2:having(“sum(age) > {0}”, 11)—>having sum(age) > 11
* 子查询
方法名解释示例
isNull字段 IS NULLisNull(“name”)—>name is null
isNotNull字段 IS NOT NULLisNotNull(“name”)—>name is not null
in字段 IN (v0, v1, …)in(“age”, 1, 2, 3)—>age in (1,2,3)
notIn字段 NOT IN (v0, v1, …)notIn(“age”, 1, 2, 3)—>age not in (1,2,3)
inSql字段 IN ( sql语句 )inSql(“id”, “select id from table where id < 3”)—>id in (select id from table where id < 3)
notInSql字段 NOT IN ( sql语句 )notInSql(“id”, “select id from table where id < 3”) —> id not in (select id from table where id < 3)
* 逻辑拼接
方法名解释示例
func主要解决条件拼接func(i -> if(true) {i.eq(“id”, 1)} else {i.ne(“id”, 1)})
or拼接 OReq(“id”,1).or().eq(“name”,“老王”)—>id = 1 or name = ‘老王’
andAND 嵌套and(i -> i.eq(“name”, “李白”).ne(“status”, “活着”))—>and (name = ‘李白’ and status <> ‘活着’)
nested用于多条件拼接时nested(i -> i.eq(“name”, “李白”).ne(“status”, “活着”))—>(name = ‘李白’ and status <> ‘活着’)
apply用于拼接SQL语句例1:apply(“id = 1”)—>id = 1,例2:apply(“id = {0}”,1)—>id = 1,例3:apply(“name like {0} and age > {1}”,“%J%”,18) —>name like ‘%J%’ and age > 18
last无视优化规则直接拼接到 sql 的最后last(“limit 1”) —>在SQL语句最后面拼接:limit 1
exists拼接 EXISTS ( sql语句 )exists(“select id from table where age = 1”)—>exists (select id from table where age = 1)
notExists拼接 NOT EXISTS ( sql语句 )notExists(“select id from table where age = 1”)—>not exists (select id from table where age = 1)

3:创建Wrapper对象:

  • Wrappers静态方法:public static QueryWrapper query()
    • QueryWrapper wrapper = Wrappers.query();
  • 通过QueryWrapper对象的构造方法:public QueryWrapper()
    • QueryWrapper wrapper2 = new QueryWrapper<>();

4:QueryMapper

QueryMapper是AbstractWrapper的子类,主要用于查询指定字段,方法列表如下:

方法名解释示例
select(String… sqlSelect)设置查询字段例1:select(“id”, “name”, “age”),例2:select(i -> i.getProperty().startsWith(“test”))
 // 选择查询的字段
    @Test
    public void test1() throws Exception {
        QueryWrapper<User> wrapper = Wrappers.query();

        // 确定要查询的字段
        wrapper.select("id", "name", "sex");

        // in
        wrapper.in("id","1","2");

        // SQL: SELECT id,name,sex FROM user WHERE (id IN (?,?))
        List<User> userList = userMapper.selectList(wrapper);

        userList.forEach(System.out::println);
    }

5:UpdateWrapper

UpdateWrapper也是AbstractWrapper的子类,因此UpdateWrapper也具备之前的那些查询方法,不同的是,UpdateMapper在那些方法基础之上还提供了很多有关于更新操作的方法;

方法名解释示例
set(String column, Object val)设置查询字段例1:set(“name”, “张三”),例2:set(“name”, “”)—>数据库字段值变为空字符串,例3:set(“name”, null)—>数据库字段值变为null
setSql(String sql)设置set子句的部分SQL例1:setSql(“name = ‘张三’”),例2:setSql(“name = ‘张三’,age=22 where id=1”)
	@Test
    public void test4() throws Exception {
        User user = new User();
        user.setId(1L);

        // user当做查询条件
        UpdateWrapper<User> wrapper = Wrappers.update(user);
        wrapper.set("name", "xiaohui");
        wrapper.set("sex", "0");
        wrapper.set("age", "22");

        // SQL : UPDATE user SET name=?,sex=?,age=? WHERE id=?
        userMapper.update(null, wrapper);
    }

	@Test
    public void test5() throws Exception {
        UpdateWrapper<User> wrapper = Wrappers.update();
        wrapper.setSql("name='abc',sex='0',age=18 where id=1");

        // SQL: UPDATE user SET name='abc',sex='0',age=18 where id=1
        userMapper.update(null, wrapper);
    }

6:LambdaQueryWrapper

LambdaQueryWrapper是QueryWrapper的子类,具备QueryWrapper的所有方法,在QueryWrapper的方法上提供了一系列有关于方法链的操作;

	@Test
    public void test1() throws Exception {

        LambdaQueryWrapper<User> wrapper = Wrappers.lambdaQuery();        
       
        wrapper.in(User::getId,"1","2","3")
                .like(User::getName,"a")
                .select(User::getId,User::getName,User::getAge);

        List<User> userList = userMapper.selectList(wrapper);
        for (User user : userList) {
            System.out.println(user);
        }
    }

7:LambdaUpdateMapper

LambdaUpdateMapper同样是UpdateMapper的子类,具备UpdateMapper的所有方法,在UpdateMapper的方法上提供了一系列有关于方法链式的操作;

 @Test
    public void test2() throws Exception {

        LambdaUpdateWrapper<User> wrapper = Wrappers.lambdaUpdate();

        wrapper.eq(User::getId,"1").set(User::getName,"lili").set(User::getAge,18);

        userMapper.update(null,wrapper);
    }

MyBatis Plus的Service查询

1:通用Service简介

通用 Service CRUD 封装IService接口,进一步封装 CRUD 采用 get 查询单行、remove删除、list 查询集合、page查询分页
在这里插入图片描述

在这里插入图片描述

2:通用service常用方法

新增:

  • default boolean save(T entity):新增记录
  • boolean saveBatch(Collection entityList):批量插入
  • saveBatch(Collection entityList, int batchSize):一次性批量插入batchSize条记录
	@Test
    public void test1() throws Exception {
        User user = new User(null, "zhagnsan", "0", 21);
        userService.save(user);
    }

删除:

  • boolean removeById(Serializable id):根据id删除
  • boolean removeByMap(Map<String, Object> columnMap):根据条件删除
  • boolean remove(Wrapper queryWrapper):使用Wrapper封装条件删除
  • boolean removeByIds(Collection<? extends Serializable> idList):删除一批
	@Test
    public void test2() throws Exception {
        userService.removeById(1L);
    }

修改:

  • boolean updateById(T entity):修改
  • boolean update(Wrapper updateWrapper):根据Wrapper修改
  • boolean update(T entity, Wrapper updateWrapper):使用Wrapper查询出结果,修改为entity
  • boolean updateBatchById(Collection entityList):批量修改
  • updateBatchById(Collection entityList, int batchSize):一次性批量修改batchSize条记录
  • boolean saveOrUpdate(T entity):如果id存在则修改,如果id不存在则新增
/**
     * 如果id存在则修改,不存在则新增
     *
     * @throws Exception
     */
    @Test
    public void test3() throws Exception {
        User user = new User(1L, "zhagnsan", "0", 18);
        userService.saveOrUpdate(user);
    }

 /**
     * 根据id修改
     *
     * @throws Exception
     */
    @Test
    public void test4() throws Exception {

        User user = new User(1L, "xiaolan", "1", 18);
        userService.updateById(user);
    }

查询:

  • T getById(Serializable id):根据id查询
  • List listByIds(Collection<? extends Serializable> idList):根据一批id查询多条记录
  • List listByMap(Map<String, Object> columnMap):根据条件查询多条记录
  • T getOne(Wrapper queryWrapper):根据Wrapper查询一条记录,如果查询到多条则抛出异常
  • T getOne(Wrapper queryWrapper, boolean throwEx):根据Wrapper查询一条记录,通过throwEx决定是否抛出异常
  • int count():查询总记录数
  • int count(Wrapper queryWrapper):根据条件查询总记录数

	/**
     * 根据id查询
     *
     * @throws Exception
     */
    @Test
    public void test5() throws Exception {
        User user = userService.getById(1L);
        System.out.println(user);
    }

    /**
     * 查询列表
     *
     * @throws Exception
     */
    @Test
    public void test6() throws Exception {

        QueryWrapper<User> wrapper = Wrappers.query();
        wrapper.in("id", "1", "2");

        // 查询所有
//        List<User> userList = userService.list();

        // 通过wrapper查询
        List<User> userList = userService.list(wrapper);

        for (User user : userList) {
            System.out.println(user);
        }
    }


    /**
     * 查询总记录数
     *
     * @throws Exception
     */
    @Test
    public void test7() throws Exception {

        QueryWrapper<User> wrapper = Wrappers.query();
        wrapper.like("name", "a");

        // 查询总记录数
//        int count = userService.count();

        // 根据条件查询总记录数
        int count = userService.count(wrapper);

        System.out.println(count);
    }

分页:

  • <E extends IPage> E page(E page, Wrapper queryWrapper):带条件分页查询,当前页数据为T类型
  • <E extends IPage> E page(E page):无条件分页
  • List<Map<String, Object>> pageMaps(E page,Wrapper queryWrapper):带条件分页查询,当前页数据为HashMap类型
  • List<Map<String, Object>> pageMaps(E page):无条件分页
	/**
     * 分页查询(当前页类型为指定类型)
     *
     * @throws Exception
     */
    @Test
    public void test8() throws Exception {

        Page<User> page = new Page<>(1, 3);

        userService.page(page);

        // 当前页数据
        List<User> pageData = page.getRecords();
        for (User user : pageData) {
            System.out.println(user);
        }

        System.out.println("------------");

        System.out.println("当前页:" + page.getCurrent());
        System.out.println("每页显示的条数:" + page.getSize());
        System.out.println("总记录数:" + page.getTotal());
        System.out.println("总页数:" + page.getPages());
        System.out.println("是否有上一页:" + page.hasPrevious());
        System.out.println("是否有下一页:" + page.hasNext());
    }


    /**
     * 分页查询(当前页结果为HashMap类型)
     *
     * @throws Exception
     */
    @Test
    public void test9() throws Exception {

        Page page = new Page<>(1, 3);

        userService.pageMaps(page);

        // 当前页数据
        List<HashMap<String, Object>> pageData = page.getRecords();
        for (HashMap userMap : pageData) {
            System.out.println(userMap);
        }

        System.out.println("------------");

        System.out.println("当前页:" + page.getCurrent());
        System.out.println("每页显示的条数:" + page.getSize());
        System.out.println("总记录数:" + page.getTotal());
        System.out.println("总页数:" + page.getPages());
        System.out.println("是否有上一页:" + page.hasPrevious());
        System.out.println("是否有下一页:" + page.hasNext());
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1906469.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

OpenAI年初安全事件引发内部分裂

&#x1f989; AI新闻 &#x1f680; OpenAI年初安全事件引发内部分裂 摘要&#xff1a;《纽约时报》报道&#xff0c;OpenAI于2023年初发生安全事件&#xff0c;黑客入侵公司内部邮件系统&#xff0c;窃取敏感讨论信息&#xff0c;但未涉及客户数据和源代码。因未向执法部门…

黑马点评报错@user_script:17: user_script:17: attempt to compare nil with number

后面发现是需要预先写入缓存seckill:stock:11&#xff0c;其中11是优惠券id 我数据库里面是11 &#xff0c;这里redis里面也写了11之后就好使了

AI自动生成PPT怎么用?看完这篇文章你就知道啦

小暑&#xff0c;作为夏季的第五个节气&#xff0c;标志着炎炎夏日的正式到来。在这个时节&#xff0c;阳光明媚&#xff0c;万物生长&#xff0c;人们的心情也随着气温的升高而变得热烈。 然而&#xff0c;对于许多职场人士来说&#xff0c;小暑的到来也意味着需要准备各种汇报…

桑基气泡图 – 5个维度展示KEGG通路富集结果

2022年发表在《Nature communication》上的文章Kir2.1-mediated membrane potential promotes nutrient acquisition and inflammation through regulation of nutrient transporters fig1i使用微生信平台绘制了一张图&#xff0c;我们将其命名为“桑基气泡图”。从此&#xff…

Spring事务的进阶。@Transactional的rollbackFor和propagation属性。

1.3 事务进阶 前面我们通过spring事务管理注解Transactional已经控制了业务层方法的事务。接下来我们要来详细的介绍一下Transactional事务管理注解的使用细节。我们这里主要介绍Transactional注解当中的两个常见的属性&#xff1a; 异常回滚的属性&#xff1a;rollbackFor &…

拿客户电脑,用豆包IDE逆天改命完成需求紧急开发!被公司奖励500!

故事背景 原文链接&#xff1a;拿客户电脑&#xff0c;用豆包IDE逆天改命完成需求紧急开发&#xff01;被公司奖励500&#xff01; 前几天&#xff0c;业务拉了一个大客户&#xff0c;客户需要先看我们做的样本项目&#xff08;类似于官网首页&#xff09;&#xff0c;然后才…

一个php文件怎么实现联系表单自动发送邮件

学习PHP&#xff1a;如何编写一个自动发送邮件的联系表单处理器&#xff1f; 无论是反馈意见、业务咨询&#xff0c;还是技术支持&#xff0c;联系表单都能为用户提供便捷的交流途径。AokSend将探讨如何通过一个PHP文件实现联系表单的自动发送邮件功能。 php文件&#xff1a;…

移除元素合并两个有序数组-LeetCode

一、移除元素 . - 力扣&#xff08;LeetCode&#xff09; 题目描述&#xff1a; int removeElement(int* nums, int numsSize, int val) {int src0;int dst0;while(src<numsSize){if(nums[src]val){src;}else if (nums[src]!val){nums[dst]nums[src];src;dst;}}return dst…

Java线程的创建·启动和休眠

一.线程的创建和启动 Java中创建线程的两种方式 ◆继承java.lang.Thread类 ◆实现java.lang.Runnable接口 ◆使用线程的步骤 继承Thread类创建线程 ◆自定义线程类继承自Thread类 ◆重写run()方法&#xff0c;编写线程执行体 ◆创建线程对象&#xff0c;调用start()方法启动…

排序的总结

排序的性质 稳定性 相同的值相对顺序不变&#xff0c;对于结构体排序有意义 排序的比较 插入排序&#xff1a;时间复杂度&#xff1a;O(N^2),空间复杂度&#xff1a;O(1),稳定性&#xff1a;稳定 希尔排序&#xff1a;时间复杂度&#xff1a;O(N^1.3),空间复杂度&#xff1…

Web 基础与HTTP 协议

域名的概述 (1 )域名的结构 (2 )域名结构类型 根域&#xff1a;指的是根服务器&#xff0c;要用来管理互联网的主目录&#xff0c;全世界只有13台。1个为 主根服务器&#xff0c;放置在美国。其余12 个均为辅根服务器&#xff0c;其中9个放置在美国&#xff1b;欧 洲2个&…

桥接模式(大话设计模式)C/C++版本

桥接模式 C #include <iostream> using namespace std;class HandsetSoft // 手机软件 { public:virtual ~HandsetSoft() default;virtual void Run() 0; };class HandsetGame : public HandsetSoft // 手机游戏 { public:void Run() override{cout << "运…

Flutter【组件】标签

简介 flutter 标签组件。标签组件是一种常见的 UI 元素&#xff0c;用于显示和管理多个标签&#xff08;或标签集合&#xff09;。 github地址&#xff1a; https://github.com/ThinkerJack/jac_uikit pub地址&#xff1a;https://pub.dev/packages/jac_uikit 使用方式&…

Games101学习笔记 Lecture17 Materials and Appearances

Lecture17 Materials and Appearances 材质 BRDF一、Diffuse/Lambertian Material二、Glossy Material三、Ideal reflective/ refractive Material (BSDF)1.镜面反射2.镜面折射3.菲涅尔项 Fresnel 四、Microfacet BRDF 微表面五、Isotropic / Anisotropic Materials (BRDFs)An…

背部筋膜炎的症状及治疗

背部筋膜炎&#xff0c;也称为胸背肌筋膜炎&#xff0c;主要是由于劳损或风寒湿邪侵入引起的。其典型症状主要包括&#xff1a; 1、疼痛&#xff1a;背部筋膜一旦出现炎症性病变&#xff0c;会对周围交感神经组织产生刺激作用&#xff0c;从而引起不同程度的疼痛症状。 2、僵…

【爱上C++】vector用法详解

文章目录 一:vector简介二:vector的创建和初始化三:vector的遍历1.[]下标2.at()3.迭代器遍历4.范围for 四:vector的空间1.size2.max_size3.capacity4.reserve5.resize6.empty 五:vector的增删查改1.push_back2.pop_back3.find4.insert5.erase6.swap7.assign Hello~同学们好&…

人脸检测(Python)

目录 环境&#xff1a; 初始化摄像头&#xff1a; 初始化FaceDetector对象&#xff1a; 获取摄像头帧&#xff1a; 获取数据&#xff1a; 绘制数据&#xff1a; 显示图像&#xff1a; 完整代码&#xff1a; 环境&#xff1a; cvzone库&#xff1a;cvzone是一个基于…

初识Kettle插件

问题反馈 如有问题可通过微信公众号“假装正经的程序员”反馈 前言 由于kettle设计的特殊性&#xff0c;kettle的处理流程均是通过插件组装的形式来进行工作&#xff0c;因此kettle插件开发是目前kettle二次开发的核心内容。 插件类型 转换步骤插件&#xff1a;在kettle转换…

探索TXE、TC、RXNE标志位在串口通信中的轮询与中断应用

浅谈一下STM32串口中断之TXE,TC,RXNE标志位 之前做一个项目&#xff0c;用到了串口中断&#xff0c;但是对TXE、TC和RXNE标志位的作用和使用方法不是很清楚&#xff0c;导致在调试过程中遇到了一些问题。通过查阅相关资料和实际操作&#xff0c;我对这三个标志位有了更深入的了…

GD 32中断系统实现

1.0 中断的概念 中断&#xff1a;简单来说就是打断的意思&#xff0c;在计算机系统中CPU在执行一个操作的时候&#xff0c;有一个比当前任务更为紧急的任务需要执行,cpu暂停当前任务转而去执行更为紧急任务的操作&#xff0c;执行完更为紧急任务之后再返回来执行原来未执行完的…