MyBatisPlus 之三:BaseMapper 详解和 CRUD 案例详解

news2025/2/27 12:28:36

BaseMapper详解

1. SQL 日志开启

为了更好更快学习 MyBatisPlus ,需要配置 SQL 日志,这样方便我们能随时看到执行过程中使用的 SQL 语句,有助于理解执行原理及方便 SQL 错误调试

mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

mybatis-plus.configuration.map-underscore-to-camel-case=false 

2. BaseMapper API

BaseMapper 是 MyBatis Plus 提供的一个通用接口,它定义了一套基础的 CRUD(Create, Read, Update, Delete)操作方法。通过继承 BaseMapper,开发者可以直接在自定义的 Mapper 接口中获得这些基本的数据操作功能,而无需手动编写 SQL 语句或 XML 映射文件。

public interface BaseMapper<T> extends Mapper<T> {
    int insert(T entity);

    int deleteById(Serializable id);

    int deleteByMap(@Param("cm") Map<String, Object> columnMap);

    int delete(@Param("ew") Wrapper<T> queryWrapper);

    int deleteBatchIds(@Param("coll") Collection<? extends Serializable> idList);

    int updateById(@Param("et") T entity);

    int update(@Param("et") T entity, @Param("ew") Wrapper<T> updateWrapper);

    T selectById(Serializable id);

    List<T> selectBatchIds(@Param("coll") Collection<? extends Serializable> idList);

    List<T> selectByMap(@Param("cm") Map<String, Object> columnMap);

    T selectOne(@Param("ew") Wrapper<T> queryWrapper);

    Integer selectCount(@Param("ew") Wrapper<T> queryWrapper);

    List<T> selectList(@Param("ew") Wrapper<T> queryWrapper);

    List<Map<String, Object>> selectMaps(@Param("ew") Wrapper<T> queryWrapper);

    List<Object> selectObjs(@Param("ew") Wrapper<T> queryWrapper);

    <E extends IPage<T>> E selectPage(E page, @Param("ew") Wrapper<T> queryWrapper);

    <E extends IPage<Map<String, Object>>> E selectMapsPage(E page, @Param("ew") Wrapper<T> queryWrapper);
}

3 . 基本CRUD

1) 插入数据:
int insert(T entity);
/**
 * 1. 如果属性使用的是驼峰命名法时,生成SQL时,转为带下划线的列名。例如:bookName--book_name
 *   解决办法:
 *   a. 给属性添加注解 @TableField("bookName")
 *   b. 在配置文件中,关闭驼峰名和下划线的转换
 */
@Test
void save(){
    Book book = new Book();
    book.setPrice(34f);
    book.setAuthor("王超");
    book.setBookName("JSP开发技术");
    book.setPubDate(new Date());

    System.out.println(book);
    bookDao.insert(book);
    System.out.println(book);   //执行前 后 观察变化。主键
}

注意:

  1. 如果属性使用的是驼峰命名法时,生成SQL时,转为带下划线的列名。例如:bookName--book_name

    解决办法:

    a. 给属性添加注解 @TableField("bookName")

    b. 在配置文件中,关闭驼峰名和下划线的转换

    mybatis-plus.configuration.map-underscore-to-camel-case=false
  2. 如果指定了主键 @TableId 后,默认情况下(没有指定主键生成策略),主键会使用雪花算法生成应用于分布式系统的主键

    解决办法:

    a. 给主键指定生成策略 @TableId(value = "bookid",type = IdType.AUTO)

    b. IdType.AUTO : 主键生成有数据库端来完成,一般适用于数据库自动增长

type = IdType.INPUT :程序自己指定主键
type = IdType.ASSIGN_ID :由框架自动生成指定的主键,使用的是雪花算法
type = IdType.ASSIGN_UUID :有框架自动生成给定主键,使用算法 UUID 算法

除了AUTO 之外,都是程序指定的主键,又区分程序员自己指定还是框架自动生成。

2) 查询:
T selectById(Serializable id);

//根据指定的主键列表查询
List<T> selectBatchIds(@Param("coll") Collection<? extends Serializable> idList);
//根据map中的key-value 作为条件等值条件查询
List<T> selectByMap(@Param("cm") Map<String, Object> columnMap);
//根据构建的条件查询唯一一条记录对象
T selectOne(@Param("ew") Wrapper<T> queryWrapper);

//根据构建的条件 查询记录数
Integer selectCount(@Param("ew") Wrapper<T> queryWrapper);
//根据构建的条件 查询多条记录
List<T> selectList(@Param("ew") Wrapper<T> queryWrapper);

List<Map<String, Object>> selectMaps(@Param("ew") Wrapper<T> queryWrapper);

List<Object> selectObjs(@Param("ew") Wrapper<T> queryWrapper);

<E extends IPage<T>> E selectPage(E page, @Param("ew") Wrapper<T> queryWrapper);

<E extends IPage<Map<String, Object>>> E selectMapsPage(E page, @Param("ew") Wrapper<T> queryWrapper);

如果直接使用 selectById() 查询,结果下面语句:

/**

 * 注意:给实体类中指定主键,否则出现下面 null=?
 * SELECT bookId,bookName,author,pubdate,price FROM book WHERE null=?
   */

查不出结果的原因:不知道哪一个列是主键。所以使用了 null = ? 作为条件了

解决办法:

给属性指定主键:@TableId

@TableField 可以设置忽略 exist=true

@Data
public class Book {
    @TableId
    private Integer bookId;
    @TableField("bookName")
    private String bookName;
    private Float price;
    @TableField("pubdate")
    private Date pubDate;
    private String author;
}
selectBatchIds() 用法:
//SELECT bookid,bookName,price,pubdate,author FROM book WHERE bookid IN ( ? , ? , ? , ? , ? )
List<Integer> ids = Arrays.asList(2,3,4,26,27);
bookDao.selectBatchIds(ids);
selectByMap() 用法:
//SELECT bookid,bookName,price,pubdate,author FROM book WHERE price = ? AND bookname = ?
Map<String,Object> cond = new HashMap<>();
cond.put("price",34f);
cond.put("bookname","Java开发技术");

bookDao.selectByMap(cond);
Wrapper 用法

下面方法用法:Wrapper 用法

//根据构建的条件 查询记录数
Integer selectCount(@Param("ew") Wrapper<T> queryWrapper);
//根据构建的条件 查询多条记录
List<T> selectList(@Param("ew") Wrapper<T> queryWrapper);

下面使用方式:

QueryWrapper 可以用于构建查询的列、条件、排序、分组等要素。

    void queryByWrapper(){
       QueryWrapper<Book> queryWrapper = new QueryWrapper<>();

       queryWrapper.select("bookname","price","author");     //指定要求查询的列
       queryWrapper.gt("price",20);                            // where price > 20
       queryWrapper.le("price",80);                            // and  price <= 80
       queryWrapper.eq("bookname","Java开发实战");             // and bookname= 'Java开发实战'
       queryWrapper.between("bookid",10,50);                // and bookid between 10,50 
       bookDao.selectList(queryWrapper);

//       bookDao.selectCount(null); //无条件查询,没有where
//        bookDao.selectCount(queryWrapper); //按条件查询
    }

queryWrapper 支持链式编程方式:

queryWrapper.select("bookname","price","author")
.gt("price",20)
.le("price",80)
.eq("bookname","Java开发实战")
.between("bookid",10,50);
bookDao.selectList(queryWrapper);
selectOne()

注意:返回值只能小于等于一条才可以,否则异常。

@Test
void queryOne(){
    QueryWrapper<Book> queryWrapper = new QueryWrapper<>();
    queryWrapper.eq("bookname", "Java实战开发1")
            .eq("author","周瑜");

    Book book = bookDao.selectOne(queryWrapper);
    System.out.println(book);
}
selectMaps()

返回结果为List ,元素为Map封装的记录对象。

@Test
void queryMap(){
    List<Map<String, Object>> maps = bookDao.selectMaps(null);
    maps.forEach(System.out::println);
}
or 和 orderby
/**
 * where author='周瑜' or author='诸葛亮'
 *
 * or 和 order by
 */
@Test
public void or(){
    QueryWrapper<Book> queryWrapper = new QueryWrapper<>();
    queryWrapper.eq("author","周瑜")
            .or()
            .eq("author","诸葛亮")
            .or()
            .gt("price",30f)
            .le("price",60f); // 默认为and 关系
    queryWrapper.orderByAsc("price").orderByDesc("bookid");

    bookDao.selectList(queryWrapper);
}
分页

分页需要考虑的要素:每页行数、总记录数、总页数、当前页号、当前页要显示记录

不同数据库分页 SQL 不同。

mysql : limit start, count;

sqlserver : top ---not in

oracle : rownum

MyBatisPlus 会根据 “方言” 配置,自动生成对应数据库的 SQL 语句去执行。

代码如下:

@Test
void page(){
    Page<Book> page = new Page<>();
    page.setSize(5);    //每页显示的记录数
    page.setCurrent(3); //设置当前页       // limit startindex ,countpage
    //(curPage-1)*size 

    Page<Book> page1 = bookDao.selectPage(page, null);
    //当前的要显示的记录
    List<Book> records = page1.getRecords();
    System.out.println(page1==page);
    records.forEach(System.out::println);
}

注意:直接运行后,发现并没有实现分页。

原因:没有安装分页插件。

解决办法:去官网,查看分页插件使用方法。复制代码到项目中即可

https://mp.baomidou.com/guide/page.html

//Spring boot方式
@Configuration
//@MapperScan("com.baomidou.cloud.service.*.mapper*")
public class MybatisPlusConfig {

    // 旧版
//    @Bean
    public PaginationInterceptor paginationInterceptor() {
        PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
        // 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求  默认false
        // paginationInterceptor.setOverflow(false);
        // 设置最大单页限制数量,默认 500 条,-1 不受限制
        // paginationInterceptor.setLimit(500);
        // 开启 count 的 join 优化,只针对部分 left join
        paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));
        return paginationInterceptor;
    }

    // 最新版
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); //数据库方言
        return interceptor;
    }

}

2023最新版本的分页插件:

package com.wdzl.plus.config;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 分页插件的配置
 */
@Configuration
public class MyBatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}

注意:

  1. 修改数据库方言(类型)

  2. 使用新版。注释掉旧版,不能同时使用。

  3. 类名和方法名可以自定义

另外:上面测试代码中

可以看到 page1==page 的输出结果为 true,说明两个是同一个对象。可以直接使用page 即可,简化后:

@Test
void page(){
    Page<Book> page = new Page<>();
    page.setSize(5);    //每页显示的记录数
    page.setCurrent(3); //设置当前页       // limit startindex ,countpage

    bookDao.selectPage(page, null);
    //当前的要显示的记录
    List<Book> records = page.getRecords();
    records.forEach(System.out::println);
}
3)修改
    //update book set price=99 where bookid=?
    int updateById(@Param("et") T entity);
    //update book set price=99 where bookname=? and price<?
    int update(@Param("et") T entity, @Param("ew") Wrapper<T> updateWrapper);
    @Test
    public void update(){
//        Book book = bookDao.selectById(27);
//        book.setPrice(88f);
//        bookDao.updateById(book); //按主键修改

        //下面是按条件修改
        QueryWrapper<Book> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("price",88);
        //注意 :book参数 ,是作为修改后的目标数据。把符合条件的所有记录都修改为book相同的值。

        Book book1 = new Book();
        book1.setPrice(100f);
        bookDao.update(book1,queryWrapper);
        //update 和 updateById() 在修改时,只修改属性不为null的列。
    }

注意:

  1. 单个对象修改,一般是先查询数据,再修改个别列。
  2. 对应null 的属性,不会被修改,不会执行SQL ,只会把有值的属性生成到SQL中。
4)删除
    //按主键删除 自注释
    int deleteById(Serializable id);
    //按map中的key-value 等值条件 删除
    int deleteByMap(@Param("cm") Map<String, Object> columnMap);
    // 根据构建条件删除
    int delete(@Param("ew") Wrapper<T> queryWrapper);
    // 根据集合中主键列表删除
    int deleteBatchIds(@Param("coll") Collection<? extends Serializable> idList);
    @Test
    void delete(){
        Map<String,Object> map = new HashMap<>();
        map.put("price",44f);
        map.put("bookname","java开发");
//        bookDao.deleteByMap(map);

        //WHERE bookid IN ( ? , ? , ? , ? , ? , ? )
        List<Integer> ids = Arrays.asList(3,4,5,22,34,55);
//        bookDao.deleteBatchIds(ids);

        QueryWrapper<Book> queryWrapper = new QueryWrapper<>();
        queryWrapper.lt("price",30);
        bookDao.delete(queryWrapper);
   

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

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

相关文章

Python 多线程大批量处理文件小程序

说明 平时偶尔需要进行重复性的对文件进行重命名、格式转化等。假设以文件复制功能作为目标&#xff0c;设计一个小程序使用多线程对文件进行批量复制。&#xff08;其实以后主要目标是针对Realsense的raw文件进行批量的转化&#xff0c;并借助多线程加速&#xff09; 代码 i…

深度学习 精选笔记(12)卷积神经网络-理论基础2

学习参考&#xff1a; 动手学深度学习2.0Deep-Learning-with-TensorFlow-bookpytorchlightning ①如有冒犯、请联系侵删。 ②已写完的笔记文章会不定时一直修订修改(删、改、增)&#xff0c;以达到集多方教程的精华于一文的目的。 ③非常推荐上面&#xff08;学习参考&#x…

修改yolov9的模型打印不出来Gflops的解决办法

正在修改yolov9的模块&#xff0c;发现修改后的模型没有GFlops这个参数 解决办法&#xff1a; 找到utils/torch_utils.py这个文件&#xff0c;有一个model_info函数 然后将其中的stride改为固定的640就可以打印了。 stride max(int(model.stride.max()), 32) if hasattr(mo…

扩展学习|网络问政的价值增量与实现条件:基于数据资源挖掘的视角

文献来源&#xff1a;[1]顾丹丹傅广宛.网络问政的价值增量与实现条件:基于数据资源挖掘的视角[J].中国行政管理, 2021, 000(004):76-82.DOI:10.19735/j.issn.1006-0863.2021.04.11. 一、技术赋能网络问政的机制生成 &#xff08;一&#xff09;技术赋能网络问政的流程&#xf…

关于IP-Adapter的十几个模型,到底是干啥用的?

&#x1f3a0;背景介绍 IP-Adapter的一系列模型在stable diffusion的实际应用中&#xff0c;越来越被频繁的使用到&#xff0c;用于“换脸”或者“保证角色的一致性”&#xff0c;但是很多朋友在安装或者使用别人的工作流的时候&#xff0c;经常会遇到各种各样的问题&#xff…

【JavaScript】JavaScript 运算符 ⑤ ( 赋值运算符 | 基础赋值运算符 与 复合赋值运算符 )

文章目录 一、JavaScript 赋值运算符1、赋值运算符 概念2、基础赋值运算符 与 复合赋值运算符3、复合赋值运算符4、完整代码示例 一、JavaScript 赋值运算符 JavaScript 赋值运算符种类 : 基础赋值运算符 : 等于 : ; 复合赋值运算符 : 加等 : 减等 : -乘等 : *除等 : /取模等…

开启Safari手势支持

在使用Safari 的时候&#xff0c;大家有没有觉得不支持手势使用起来不是很方便&#xff0c; 触摸板只支持少量简单的手势&#xff0c;如缩放&#xff0c;滚动等。如果使用鼠标的用户&#xff0c;则完全无法使用手势。经过折腾研究&#xff0c;使用CirMenu应用可以完美解决这个要…

RAID技术知识详解到RAID 10的linux实现过程

1.RAID技术简介 RAID&#xff08;Redundant Array of Independent Disks&#xff09;独立磁盘冗余阵列。通俗来说就是将多个硬盘通过软件或硬件结合成虚拟单台大容量的硬盘使用。 RAID技术的特点&#xff1a; 可以自动检测故障硬盘&#xff1b; 可以重建硬盘坏道的资料&…

VBA批量绘制动态化数据图表

对于大多数使用的VBA的人来说&#xff0c;处理excel工作簿中批量数据是日常工作中常见的情形&#xff0c;但与此同时&#xff0c;VBA在批量绘图方面同样有简洁快速的特点。 说起Excel画图表&#xff0c;考虑一个问题&#xff0c;excel图表的本质是什么&#xff1f;很多人会不假…

便利店小程序有哪些功能

​便利店小程序为附近的住户提供小程序在线购物的服务。用户只需要打开小程序&#xff0c;就可以购买需要的商品&#xff0c;可以选择自取或者配送。整个过程非常简单快速。下面具体介绍便利店小程序的功能。 1. **商品展示**&#xff1a;展示便利店的商品信息&#xff0c;包括…

【C++刷题】优选算法——动态规划第一辑

1.状态表示是什么&#xff1f;简答理解是dp表里的值所表示的含义怎么来的&#xff1f;题目要求经验题目要求分析问题的过程中&#xff0c;发现重复子问题 2.状态转移方程dp[i]......细节问题&#xff1a;3.初始化控制填表的时候不越界4.填表顺序控制在填写当前状态的时候&#…

windows下修改mysql的max_allowed_packet的值

1)C:\Program Files\MySQL\MySQL Server 5.7 在MySQL 的安装目录下添加my.ini文件&#xff0c;同时添加空的data文件 2&#xff09;my.ini文件内容如下&#xff0c; [mysqld] port 3306 basedirC:\Program Files\MySQL\MySQL Server 5.7 datadirC:\Program Files\MySQL\MySQ…

软考78-上午题-【面向对象技术3-设计模式】-结构型设计模式01

一、适配器模式 1-1、意图 个类的接口转换成客户希望的另外一个接口。 Adapter 模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。 1-2、结构 适配器模式分为&#xff1a; 1、适配器类模式&#xff1b; 2、适配器对象模式 类适配器使用多重继承对一个接口与另…

java基础(6) IO[下] 线程(补充) XML Servlet

输出流 OutputStream OutputStream是Java标准库提供的最基本的输出流。 和InputStream类似&#xff0c;OutputStream也是抽象类&#xff0c;它是所有输出流的超类。这个抽象类定义的一个最重要的方法就是void write(int b) public abstract void write(int b) throws IOExcep…

html--宠物

文章目录 htmljscss html <!DOCTYPE html> <html lang"en" > <head><meta charset"UTF-8"><title>CodePen - Spaceworm</title><script> window.requestAnimFrame (function() {return (window.requestAnimat…

Javascript抓取京东、淘宝商品数据(商品采集商品详情图片抓取)

之前用的方法&#xff1a; let temp []var lists $(#J_goodsList li.gl-item)$.each(lists,function(idx,item){ temp.push({ id:$(item).data(sku), goods_img:$(item).find(img).attr(src), goods_name:$(item).find(.p-name em).text(), market_price:$(item).fi…

2024 年(第 12 届)“泰迪杯”数据挖掘挑战赛——B 题:基于多模态特征融合的图像文本检索完整思路与源代码分享

一、问题背景 随着近年来智能终端设备和多媒体社交网络平台的飞速发展&#xff0c;多媒体数据呈现海量增长 的趋势&#xff0c;使当今主流的社交网络平台充斥着海量的文本、图像等多模态媒体数据&#xff0c;也使得人 们对不同模态数据之间互相检索的需求不断增加。有效的信…

洛谷P8972 『GROI-R1』 一切都已过去(树上前缀和+运算符重载)

『GROI-R1』 一切都已过去 题目背景 悦关上窗&#xff0c;拉上帘布。 果然还是想不起来啊。 隐约记得曾和什么人一起做过这样的事。 仰面躺下&#xff0c;手执一只木笺。 「究竟如何&#xff0c;才能拥有“过去”啊……」 她闭上双眼。 「6 岁前的记忆……究竟如何才能…

ConsiStory:Training-Free的主体一致性生成

Overview 一、总览二、PPT详解 ConsiStory 一、总览 题目&#xff1a; Training-Free Consistent Text-to-Image Generation 机构&#xff1a;NVIDIA, Tel-Aviv University 论文&#xff1a;https://arxiv.org/pdf/2402.03286.pdf 代码&#xff1a;https://consistory-paper.g…

Python自动获取指定上市公司的所有财务数据(资产负债表,利润表,现金流量表)

案例背景 很多经管类同学找财务数据都很困难&#xff0c;去找一个个查找特定的公司&#xff0c;然后又要去同花顺或者东方财富网一年一年的去查看报表&#xff0c;一年一年的数据一个个填入...太慢了。 tushare能获取金融数据的接口&#xff0c;他有资产负债表&#xff0c;利…