MybatisPlus的学习

news2024/12/23 12:02:26

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

基于Mapper接口CRUD

Insert方法

// 插入一条记录
// T 就是要插入的实体对象
// 默认主键生成策略为雪花算法
int insert(T entity);
类型参数名描述
Tentity实体对象

 Delete方法

// 根据 entity 条件,删除记录
int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper);

// 删除(根据ID 批量删除)
int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);

// 根据 ID 删除
int deleteById(Serializable id);

// 根据 columnMap 条件,删除记录
int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
类型参数名描述
Wrapper<T>wrapper实体对象封装操作类(可以为 null)
Collection<? extends Serializable>idList主键 ID 列表(不能为 null 以及 empty)
Serializableid主键 ID
Map<String, Object>columnMap表字段 map 对象

 Update方法

// 根据 whereWrapper 条件,更新记录
int update(@Param(Constants.ENTITY) T updateEntity, 
            @Param(Constants.WRAPPER) Wrapper<T> whereWrapper);

// 根据 ID 修改  主键属性必须值
int updateById(@Param(Constants.ENTITY) T entity);
类型参数名描述
Tentity实体对象 (set 条件值,可为 null)
Wrapper<T>updateWrapper实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)

Select方法 

// 根据 ID 查询
T selectById(Serializable id);

// 根据 entity 条件,查询一条记录
T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

// 查询(根据ID 批量查询)
List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);

// 根据 entity 条件,查询全部记录
List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

// 查询(根据 columnMap 条件)
List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);

// 根据 Wrapper 条件,查询全部记录
List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

// 根据 Wrapper 条件,查询全部记录。注意: 只返回第一个字段的值
List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

// 根据 entity 条件,查询全部记录(并翻页)
IPage<T> selectPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

// 根据 Wrapper 条件,查询全部记录(并翻页)
IPage<Map<String, Object>> selectMapsPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

// 根据 Wrapper 条件,查询总记录数
Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
类型参数名描述
Serializableid主键 ID
Wrapper<T>queryWrapper实体对象封装操作类(可以为 null)
Collection<? extends Serializable>idList主键 ID 列表(不能为 null 以及 empty)
Map<String, Object>columnMap表字段 map 对象
IPage<T>page分页查询条件(可以为 RowBounds.DEFAULT)

 常用的方法的代码样例

 //查询
    @Test
    public void testSelect() {
        System.out.println(("----- selectAll method test ------"));
        List<User> userList = userMapper.selectList(null);
        System.out.println(userList);

        List<Long> list =new ArrayList<>();
        list.add(1L);
        list.add(3L);
        List<User> users=userMapper.selectBatchIds(list);
        System.out.println("users = " + users);
    }
    //添加
    @Test
    public void testAdd() {
        User user = new User();
        user.setAge(12);
        user.setEmail("xxx");
        user.setName("大撒");
        int insert = userMapper.insert(user);
        System.out.println(insert);

    }
    //删除
    @Test
    public void testDelete() {
        int i = userMapper.deleteById("1831895769316061185");
        System.out.println("i = " + i);
        Map map=new HashMap<>();
        map.put("age",20);
        int i1 = userMapper.deleteByMap(map);
        System.out.println("i1 = " + i1);
        
    }
    //修改
    @Test
    public void testUpdate() {
        User user=new User();
        user.setId(1L);
        user.setAge(21);
        int i = userMapper.updateById(user);
        System.out.println("i = " + i);


        User user1=new User();
        user.setAge(21);
        int i1 = userMapper.update(user,null);
        System.out.println("i1 = " + i1);
    }

基于Service接口CRUD

对比Mapper接口CRUD区别:

- service添加了批量方法

- service层的方法自动添加事务

使用Iservice接口方式

接口继承IService接口

public interface UserService extends IService<User> {
}

类继承ServiceImpl实现类

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper,User> implements UserService{

}

 具体方法参考官方文档MyBatis-Plus 🚀 为简化开发而生 (baomidou.com)icon-default.png?t=O83Ahttps://baomidou.com/

MybatisPlus分页查询实现步骤

1.导入分页插件

下面这段代码放到启动类里面

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

2.使用分页查询

@Test
public void testPageQuery(){
    //设置分页参数
    Page<User> page = new Page<>(1, 5);
    userMapper.selectPage(page, null);
    //获取分页数据
    List<User> list = page.getRecords();
    list.forEach(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());
}

条件构造器使用

使用MyBatis-Plus的条件构造器,你可以构建灵活、高效的查询条件,而不需要手动编写复杂的

SQL 语句。它提供了许多方法来支持各种条件操作符,并且可以通过链式调用来组合多个条件。

这样可以简化查询的编写过程,并提高开发效率。

条件构造器继承结构

Wrapper : 条件构造抽象类,最顶端父类

- AbstractWrapper : 用于查询条件封装,生成 sql 的 where 条件

    - QueryWrapper : 查询/删除条件封装
    - UpdateWrapper : 修改条件封装
    - AbstractLambdaWrapper : 使用Lambda 语法
        - LambdaQueryWrapper :用于Lambda语法使用的查询Wrapper
        - LambdaUpdateWrapper : Lambda 更新封装Wrapper

 不使用QueryWrapper进行修改的原因

1.需要创建对应的实体类

2.无法将列值修改为null值!

使用queryWrapper修改

@Test
public void test04() {
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    //将年龄大于20并且用户名中包含有a或邮箱为null的用户信息修改
    //UPDATE t_user SET age=?, email=? WHERE username LIKE ? AND age > ? OR email IS NULL)
    queryWrapper
            .like("username", "a")
            .gt("age", 20)
            .or()
            .isNull("email");
    User user = new User();
    user.setAge(18);
    user.setEmail("user@atguigu.com");
    int result = userMapper.update(user, queryWrapper);
    System.out.println("受影响的行数:" + result);
}

使用updateWrapper修改

@Test
public void testQuick2(){

    UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
    //将id = 3 的email设置为null, age = 18
    updateWrapper.eq("id",3)
            .set("email",null)  // set 指定列和结果
            .set("age",18);
    //如果使用updateWrapper 实体对象写null即可!
    int result = userMapper.update(null, updateWrapper);
    System.out.println("result = " + result);

}

LambdaQueryWrapper对比QueryWrapper优势

QueryWrapper 示例代码:

QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name", "John")
  .ge("age", 18)
  .orderByDesc("create_time")
  .last("limit 10");
List<User> userList = userMapper.selectList(queryWrapper);

LambdaQueryWrapper 示例代码:

LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();

lambdaQueryWrapper.eq(User::getName, "John")
  .ge(User::getAge, 18)
  .orderByDesc(User::getCreateTime)
  .last("limit 10");
List<User> userList = userMapper.selectList(lambdaQueryWrapper);

从上面的代码对比可以看出,相比于 QueryWrapper,LambdaQueryWrapper 使用了实体类的属

性引用(例如 User::getName、User::getAge),而不是字符串来表示字段名,这提高了代码的可

读性和可维护性。

核心注解使用

@TableName注解

- 描述:表名注解,标识实体类对应的表

- 使用位置:实体类

@TableName("sys_user") //对应数据库表名
public class User {
    private Long id;
    private String name;
    private Integer age;
    private String email;
}

特殊情况:如果表名和实体类名相同(忽略大小写)可以省略该注解!

其他解决方案:全局设置前缀

mybatis-plus: # mybatis-plus的配置
  global-config:
    db-config:
      table-prefix: sys_ # 表名前缀字符串

@TableId 注解

- 描述:主键注解

- 使用位置:实体类主键字段

@TableName("sys_user")
public class User {
    @TableId(value="主键列名",type=主键策略)
    private Long id;
    private String name;
    private Integer age;
    private String email;
}
属性类型必须指定默认值描述
valueString""主键字段名
typeEnumIdType.NONE指定主键类型

IdType属性可选值: 

描述
AUTO数据库 ID 自增 (mysql配置主键自增长)
ASSIGN_ID(默认)分配 ID(主键类型为 Number(Long )或 String)(since 3.3.0),使用接口IdentifierGenerator的方法nextId(默认实现类为DefaultIdentifierGenerator雪花算法)

 全局配置修改主键策略:

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

在以下场景下,添加`@TableId`注解是必要的:

1. 实体类的字段与数据库表的主键字段不同名:如果实体类中的字段与数据库表的主键字段不一

致,需要使用`@TableId`注解来指定实体类中表示主键的字段。

2. 主键生成策略不是默认策略:如果需要使用除了默认主键生成策略以外的策略,也需要添加

@TableId`注解,并通过`value`属性指定生成策略。

@TableField注解

描述:字段注解(非主键)

@TableName("sys_user")
public class User {
    @TableId
    private Long id;
    @TableField("nickname")
    private String name;
    private Integer age;
    private String email;
}
属性类型       必须指定默认值描述
value    String    否 " "数据库字段名
exist     boolean    否 true            是否为数据库表字段

逻辑删除实现

概念:

逻辑删除,可以方便地实现对数据库记录的逻辑删除而不是物理删除。逻辑删除是指通过更改记录的状态或添加标记字段来模拟删除操作,从而保留了删除前的数据,便于后续的数据分析和恢复。

- 物理删除:真实删除,将对应数据从数据库中删除,之后查询不到此条被删除的数据

- 逻辑删除:假删除,将对应数据中代表是否被删除字段的状态修改为“被删除状态”,之后在数据     库中仍旧能看到此条数据记录

逻辑删除实现步骤:

1.数据库和实体类添加逻辑删除字段

2.指定逻辑删除字段和属性值

   a.单一指定

@Data
public class User {

   // @TableId
    private Integer id;
    private String name;
    private Integer age;
    private String email;
    
    @TableLogic
    //逻辑删除字段 int mybatis-plus下,默认 逻辑删除值为1 未逻辑删除 1 
    private Integer deleted;
}

b.全局指定

mybatis-plus:
  global-config:
    db-config:
      logic-delete-field: deleted # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
      logic-delete-value: 1 # 逻辑已删除值(默认为 1)
      logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)

逻辑删除以后,没有真正的删除语句,删除改为修改语句!

使用mybatis-plus数据使用乐观锁

1. 添加版本号更新插件

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

2.乐观锁字段添加@Version注解

- 支持的数据类型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime

- 仅支持 `updateById(id)` 与 `update(entity, wrapper)` 方法

@Version
private Integer version;

3.正常更新使用即可

//演示乐观锁生效场景
@Test
public void testQuick7(){
    //步骤1: 先查询,在更新 获取version数据
    //同时查询两条,但是version唯一,最后更新的失败
    User user  = userMapper.selectById(5);
    User user1  = userMapper.selectById(5);

    user.setAge(20);
    user1.setAge(30);

    userMapper.updateById(user);
    //乐观锁生效,失败!
    userMapper.updateById(user1);
}

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

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

相关文章

直播录屏怎么录视频?自制教程分享,一键录制精彩瞬间

在数字时代&#xff0c;直播已成为连接观众与内容创作者的重要桥梁&#xff0c;想要留住直播中的每一个精彩瞬间&#xff0c;录屏工具不可或缺。今天&#xff0c;我们就来分享一份自制教程&#xff0c;介绍三款实用的录屏方法&#xff0c;需要的朋友抓紧来看看吧~ 方法一&#…

【Python机器学习】循环神经网络(RNN)——传递数据并训练

与其他Keras模型一样&#xff0c;我们需要向.fit()方法传递数据&#xff0c;并告诉它我们希望训练多少个训练周期&#xff08;epoch&#xff09;&#xff1a; model.fit(X_train,y_train,batch_sizebatch_size,epochsepochs,validation_data(X_test,y_test)) 因为个人小电脑内…

Python函数:匿名函数(lambda)④

文章目录 引言1. 什么是匿名函数&#xff08;lambda&#xff09;&#xff1f;1.1 lambda 函数的语法1.2 示例 2. lambda 函数的使用场景2.1 作为参数传递给高阶函数2.1.1 使用 map2.1.2 使用 filter2.1.3 使用 reduce 2.2 排序2.3 在数据结构中使用lambda函数 3. lambda 函数的…

油耳要怎么清洁耳朵才干净?比较推荐哪种可视耳勺

油耳朵的小伙伴们有没有这样的烦恼呢&#xff1f;一两天不清理耳朵就会发痒&#xff0c;日常用棉签清洁耳朵老是清理不干净&#xff0c;而且在转动棉签时还会把棉絮残留在耳道中&#xff1b;用普通耳勺清理又容易刮破耳道&#xff0c;导致耳朵感染。对于油耳朵的小伙伴&#xf…

潘多拉的盒子还是阿拉丁的神灯:揭示RAG噪声在大语言模型中的作用

一、结论写在前面 论文来自清华大学、北京国家信息科学与技术研究中心 论文标题&#xff1a;Pandora’s Box or Aladdin’s Lamp: A Comprehensive Analysis Revealing the Role of RAG Noise in Large Language Models 论文链接&#xff1a;https://arxiv.org/pdf/2408.135…

参赛心得和思路分享:2021第二届云原生编程挑战赛2: 实现一个柔性集群调度机制

关联比赛: 2021第二届云原生编程挑战赛2&#xff1a;实现一个柔性集群调度机制 参赛心得 历时快两个月的第二届云原生编程挑战赛结束了&#xff0c;作为第一次参赛的萌新&#xff0c;拿下了28名的成绩&#xff0c;与第一名差了19万分&#xff0c;因为赛制时间太长&#xff0c…

【C语言进阶】C语言动态内存管理:深入理解malloc、calloc与realloc

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ ⏩收录专栏⏪&#xff1a;C语言 “ 登神长阶 ” &#x1f921;往期回顾&#x1f921;&#xff1a;C语言自定义类型 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀C语言动态内存管理 &#…

线路及接口基础知识

目录 一、常见视频接口 一、常见视频接口

电话外呼系统对比普通电销有什么区别

电话外呼系统与普通电销在多个方面存在显著差异&#xff0c;这些差异主要体现在效率、成本、智能化程度、数据管理和客户体验等方面。以下是具体的对比分析&#xff1a; ### 一、效率差异 * **电话外呼系统**&#xff1a; - **高效性**&#xff1a;可以同时拨打大量电话&…

刚开始学精益六西格玛管理方法?这份指南建议收藏

精益六西格玛管理方法&#xff0c;作为两大管理哲学的完美结合&#xff0c;正逐渐成为众多企业转型升级的利器。对于刚开始接触这一领域的你来说&#xff0c;掌握精益六西格玛管理的精髓并有效应用于实践中&#xff0c;无疑是一项既具挑战性又极具价值的任务。本文&#xff0c;…

[Linux#48][网络] 令牌环网 | IPv4 | socket 套接字 | TCP | UDP | 网络字节序列

目录 1.网络 1.0 令牌环网&#xff08;了解&#xff09; 1.1 IP 地址 1.3 网络通信的基本脉络 IPv4地址解释 2.Socket 编程预备 2.1 端口号 2.2 传输层协议 2.3 网络字节序列 库函数定义 函数说明 1.网络 1.0 令牌环网&#xff08;了解&#xff09; 相同令牌时&am…

Nest.js 实战 (十三):实现 SSE 服务端主动向客户端推送消息

前言 假如系统又一个这样的业务场景&#xff1a;已登录的用户发起流程或者发布消息之后&#xff0c;需要弹窗通知其他已登录的用户&#xff0c;我们应该如何实现&#xff1f; 在设计实时通信场景时&#xff0c;我们面临的主要挑战是如何有效地通知所有已登录的用户有关新流程…

关于 PreparedStatement

Mysql 层面的语法也支持 prepare 这个确实第一次见 PREPARE prepares a statement for execution (see Section 13.5.1, “PREPARE Statement”).EXECUTE executes a prepared statement (see Section 13.5.2, “EXECUTE Statement”).DEALLOCATE PREPARE releases a prepared…

半天玩转大模型技术之RAG

引 言 当前大模型在金融行业最广泛的应用之一就是知识问答&#xff0c;而支撑该应用的技术正是当下火热的检索增强生成&#xff08;Retrieval Augmented Generation&#xff09;技术&#xff0c;简称 RAG。因企业具体的业务往往需要注入特定的知识&#xff0c;比如ChatBI中企业…

Google出了一个黑科技,可以把书变成真人多角色对话的音频,效果真的很牛!

大家有没有想过,像读书、查资料这种事情,如果可以用听的,效率会不会更高?我想大部分人都曾有过这种念头。尤其是在这信息爆炸的时代,手头上有大量的书籍、论文等资源,但我们根本没时间一页一页地去翻。对吧?这时,Google Illuminate 的出现,简直像是为我们解了燃眉之急…

力扣: 赎金信

文章目录 需求分析及编码结尾 需求 给你两个字符串&#xff1a;ransomNote 和 magazine &#xff0c;判断 ransomNote 能不能由 magazine 里面的字符构成。 如果可以&#xff0c;返回 true &#xff1b;否则返回 false 。 magazine 中的每个字符只能在 ransomNote 中使用一次…

kubernetes中的微服务Service(ClusterIP、NodePort、LoadBalancer)

目录 一 、什么是微服务 二 、微服务的类型 三、 ipvs模式 3.1 ipvs模式配置方式 四、微服务类型详解 4.1 clusterip 4.2 ClusterIP中的特殊模式headless 4.3 nodeport 4.4 loadbalancer 4.5 metalLB 4.6 externalname 五 Ingress-nginx 5.1 ingress-nginx功能 5.2…

【大模型专栏—入门篇】CUDA入门与AutoDL“炼丹”

大模型专栏介绍 &#x1f60a;你好&#xff0c;我是小航&#xff0c;一个正在变秃、变强的文艺倾年。 &#x1f514;本文为大模型专栏子篇&#xff0c;大模型专栏将持续更新&#xff0c;主要讲解大模型从入门到实战打怪升级。如有兴趣&#xff0c;欢迎您的阅读。 &#x1f4…

PointNet++改进策略 :模块改进 | SWA| PVT,融入Transformer的点云与体素的模块同时提升模型精度和效率

目录 介绍PVT原理PVT的核心思想和结构PVT模块结构体素分支点分支 代码实现 论文题目&#xff1a;PVT: Point-Voxel Transformer for Point Cloud Learning发布期刊&#xff1a;International Journal of Intelligent Systems通讯地址&#xff1a;杭州电子科技大学&伦敦大学…

善于善行——贵金属回收

在当今社会&#xff0c;贵金属回收已成为一项日益重要的产业。随 着科技的不断进步和人们对资源可持续利用的认识逐渐提高&#xff0c;贵金属回收的现状也备受关注。 目前&#xff0c;贵金属回收市场呈现出蓬勃发展的态势。一方面&#xff0c;贵金属如金、银、铂、钯等在众多领…