Java_MyBatisPlus

        MyBatisPlus属于是MyBatis的拓展,不影响原MyBatis框架下的代码运行,并对MyBatis框架进行拓展及优化。

使用步骤:

注意:继承BaseMapper时要填写泛型为要操作的实体类。

基本原理:

        MyBatisPlus通过扫描实体类,并基于反射获取实体类信息作为数据库表信息。

并且满足下面三点:

        ·类名驼峰转下划线作为表名

        ·名为id的字段作为主键

        ·变量名驼峰转下划线作为表的字段

        (createTime -> create_time)

常见注解:

常见配置:

        MyBatisPlus的配置项继承了MyBatis原生配置和一些自己特有的配置。例如:

注意:除去第一个别名扫描包,其他的配置在默认情况下就是这样配置的。

对MyBatis-Plus中的wrapper进行测试:

    @Testvoid testLambdaQueryWrapper1() {//查询用户名中有“o”且余额为1000的用户的id、userName、info、balanceLambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<User>().select(User::getId, User::getUsername, User::getInfo, User::getBalance).like(User::getUsername, "o").ge(User::getBalance, 1000);List<User> users = userMapper.selectList(wrapper);users.forEach(System.out::println);}@Testvoid testLambdaQueryWrapper2() {//更新jack的余额为2000User user = new User();user.setBalance(2000);LambdaQueryWrapper wrapper = new LambdaQueryWrapper<User>().eq(User::getUsername, "jack");userMapper.update(user, wrapper);}@Testvoid testLambdaUpdateWrapper() {//更新id为1,2,4的用户的余额,扣200/*update set balance = balance - 200 where id in (1,2,4)*/List<Long> ids = List.of(1L, 2L, 4L);LambdaUpdateWrapper<User> wrapper = new LambdaUpdateWrapper<User>().setSql("balance = balance - 200").in(User::getId, ids);userMapper.update(null, wrapper);}

自定义SQL:

操作步骤:

Service接口:

使用流程:

实现下面接口:

代码:

Controller:
@RestController
@RequestMapping("/users")
@Api(tags = "用户管理接口")
@RequiredArgsConstructor
public class UserController {private final IUserService userService;@ApiOperation("新增用户接口")@PostMappingpublic void save(@RequestBody UserFormDTO userDTO) {User user = BeanUtil.copyProperties(userDTO, User.class);userService.save(user);}@ApiOperation("删除用户接口")@DeleteMapping("/{id}")public void delete(@ApiParam("用户id") @PathVariable Long id) {userService.removeById(id);}@ApiOperation("根据id查询用户接口")@GetMapping("/{id}")public UserVO get(@ApiParam("用户id") @PathVariable Long id) {User user = userService.getById(id);UserVO userVO = BeanUtil.copyProperties(user, UserVO.class);return userVO;}@ApiOperation("根据id批量查询接口")@GetMappingpublic List<UserVO> list(@ApiParam("用户id集合") @RequestParam("ids") List<Long> ids) {List<User> users = userService.listByIds(ids);List<UserVO> userVOS = BeanUtil.copyToList(users, UserVO.class);return userVOS;}@ApiOperation("根据id扣减余额接口")@PutMapping("/{id}/deduction/{money}")public void deductBalance(@ApiParam("用户id") @PathVariable Long id, @ApiParam("扣减金额") @PathVariable Integer money) {userService.deductBalance(id, money);}}
Service:
public interface IUserService extends IService<User> {void deductBalance(Long id, Integer money);
}
ServiceImpl:
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {@Overridepublic void deductBalance(@Param("id") Long id, @Param("money") Integer money) {//1.查询用户信息User user = getById(id);//2.判断用户状态if(user == null || user.getStatus() == 2) {throw new RuntimeException("用户状态异常!");}//3.判断用户余额if(user.getBalance() < money) {throw new RuntimeException("用户余额不足!");}//4.扣除余额baseMapper.deductBalance(id, money);}
}
Mapper:
public interface UserMapper extends BaseMapper<User> {void updateBalanceByIds(@Param("ew") LambdaUpdateWrapper<User> wrapper, @Param("amount") int amount);@Update("update user set balance = balance - #{money} where id = #{id}")void deductBalance(Long id, Integer money);
}

Lambda查询:

        lambda查询功能很强大,除去下面例题使用的list,还有查询一个时使用的one,分页查询使用的page,统计使用的count。

代码演示:

Controller:
    @ApiOperation("根据复杂条件查询用户接口")@GetMapping("/list")public List<UserVO> queryUsers(UserQuery query) {//1.查询用户POList<User> users = userService.queryUsers(query.getName(), query.getStatus(), query.getMinBalance(), query.getMaxBalance());//2.将PO拷贝到VOreturn BeanUtil.copyToList(users, UserVO.class);}
Service:
List<User> queryUsers(String name, Integer status, Integer minBalance, Integer maxBalance);
ServiceImpl:
    @Overridepublic List<User> queryUsers(String name, Integer status, Integer minBalance, Integer maxBalance) {return lambdaQuery().like(name != null, User::getUsername, name).eq(status != null, User::getStatus, status).ge(minBalance != null, User::getBalance, minBalance).le(maxBalance != null, User::getBalance, maxBalance).list();}

Lambda更新

代码演示:

 Controller:
    @ApiOperation("根据id扣减余额接口")@PutMapping("/{id}/deduction/{money}")public void deductBalance(@ApiParam("用户id") @PathVariable Long id, @ApiParam("扣减金额") @PathVariable Integer money) {userService.deductBalance(id, money);}
Service:
void deductBalance(Long id, Integer money);
ServiceImpl:
@Overridepublic void deductBalance(@Param("id") Long id, @Param("money") Integer money) {//1.查询用户信息User user = getById(id);//2.判断用户状态if (user == null || user.getStatus() == 2) {throw new RuntimeException("用户状态异常!");}//3.判断用户余额if (user.getBalance() < money) {throw new RuntimeException("用户余额不足!");}//4.扣除余额int remainBalance = user.getBalance() - money;lambdaUpdate().set(User::getBalance, remainBalance).set(remainBalance == 0, User::getStatus, 2).eq(User::getId, id).eq(User::getBalance, user.getBalance())//乐观锁 先比较再更新.update();}

        在业务层,如果两个线程同时查询同一个用户的信息,并且都扣除100余额,如果不进行加锁那么结果余额只会减少100,所以这里采用乐观锁,先比较数据库中的余额信息与查询到的用户余额信息是否一致,一致再更新数据。

批量新增:

批处理方案:

        ·普通for循环逐条插入,速度极差,不推荐

        ·MP的批量新增,基于预编译的批处理,性能不错

        ·配置jdbc的参数,设置rewriteBatchedStatements为true,性能最好

配置:

DB静态工具:

逻辑删除:

        逻辑删除即删除数据时,通过修改一个特殊的字段值,来进行逻辑上的删除,而不是真正的删除数据,比如添加字段deleted,它为false即这条数据没被删除,它为true即这条数据被删除

问题:

枚举处理器:

        实现PO类中枚举类型变量与数据库字段的转换:

User和UserVO:

@Data
public class User {/*** 用户id*/@TableId(value = "id", type = IdType.AUTO)private Long id;/*** 用户名*/private String username;/*** 密码*/private String password;/*** 注册手机号*/private String phone;/*** 详细信息*/private String info;/*** 使用状态(1正常 2冻结)*/private UserStatus status;/*** 账户余额*/private Integer balance;/*** 创建时间*/private LocalDateTime createTime;/*** 更新时间*/private LocalDateTime updateTime;
}
@Data
@ApiModel(description = "用户VO实体")
public class UserVO {@ApiModelProperty("用户id")private Long id;@ApiModelProperty("用户名")private String username;@ApiModelProperty("详细信息")private String info;@ApiModelProperty("使用状态(1正常 2冻结)")private UserStatus status;@ApiModelProperty("账户余额")private Integer balance;@ApiModelProperty("用户的收货地址")private List<AddressVO> addresses;
}

①枚举类:

public enum UserStatus {NORMAL(1,"正常"),FROZEN(2,"冻结"),;@EnumValue //枚举类与数据库进行转换字段private final int value;@JsonValue //设置返回值格式private final String desc;UserStatus(int value, String desc) {this.value = value;this.desc = desc;}
}

②在配置文件中进行配置:

mybatis-plus:configuration:default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler

JSON处理器:

分页查询:

①先配置插件

@Configuration
public class MyBatisConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();//创建分页插件PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);paginationInnerInterceptor.setMaxLimit(1000L);//添加分页插件interceptor.addInnerInterceptor(paginationInnerInterceptor);return interceptor;}}

②使用插件:

PageQuery:
@Data
@ApiModel(description = "分页查询实体")
public class PageQuery {@ApiModelProperty("页码")private Long pageNo = 1L;@ApiModelProperty("页大小")private Long pageSize = 5L;@ApiModelProperty("排序字段")private String sortBy;@ApiModelProperty("是否升序")private Boolean isAsc = true;public <T> Page<T> toMpPage(OrderItem ... items) {//1.分页条件Page<T> page = Page.of(pageNo, pageSize);//2.排序条件if (StrUtil.isNotBlank(sortBy)) {//不为空page.addOrder(new OrderItem(sortBy, isAsc));} else if (items != null) {//为空,默认排序page.addOrder(items);}return page;}public <T> Page<T> toMpPage(String defaultSortBy, Boolean defaultAsc) {return toMpPage(new OrderItem(defaultSortBy, defaultAsc));}public <T> Page<T> toMpPageDefaultSortByCreateTime() {return toMpPage(new OrderItem("create_time", false));}public <T> Page<T> toMpPageDefaultSortByUpdateTime() {return toMpPage(new OrderItem("update_time", false));}}
pageDTO:
@Data
@ApiModel(description = "分页结果")
public class PageDTO<T> {@ApiModelProperty("总条数")private Long total;@ApiModelProperty("总页数")private Long pages;@ApiModelProperty("集合")private List<T> list;public static <PO, VO> PageDTO<VO> of(Page<PO> p, Class<VO> clazz) {PageDTO<VO> dto = new PageDTO<>();//1.总条数dto.setTotal(p.getTotal());//2.总页数dto.setPages(p.getPages());//3.当前页数据List<PO> records = p.getRecords();if(CollUtil.isEmpty(records)) {dto.setList(Collections.emptyList());return dto;}//4.拷贝user的VOdto.setList(BeanUtil.copyToList(records, clazz));//5.返回return dto;}public static <PO, VO> PageDTO<VO> of(Page<PO> p, Function<PO, VO> convertor) {PageDTO<VO> dto = new PageDTO<>();//1.总条数dto.setTotal(p.getTotal());//2.总页数dto.setPages(p.getPages());//3.当前页数据List<PO> records = p.getRecords();if(CollUtil.isEmpty(records)) {dto.setList(Collections.emptyList());return dto;}//4.拷贝user的VOdto.setList(records.stream().map(convertor).collect(Collectors.toList()));//5.返回return dto;}}
Controller:
    @ApiOperation("根据条件分页查询用户接口")@GetMapping("/page")public PageDTO<UserVO> queryUsersPage(UserQuery query) {return userService.pageUsersPage(query);}
Service:
    PageDTO<UserVO> pageUsersPage(UserQuery query);
ServiceImpl:
    @Overridepublic PageDTO<UserVO> pageUsersPage(UserQuery query) {String name = query.getName();Integer status = query.getStatus();//1.构建分页条件Page<User> page = query.toMpPageDefaultSortByUpdateTime();//2.分页查询Page<User> p = lambdaQuery().like(name != null, User::getUsername, name).eq(status != null, User::getStatus, status).page(page);//3.封装VO结果return PageDTO.of(p, UserVO.class);}

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

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

相关文章

怎么给PDF文件设置加密保护?有哪些方法?

pdf作为一种便携式文档&#xff0c;是展示内容的首选&#xff0c;目前也已广泛应用于交换和分享等&#xff0c;例如内部报告以及商业提案等。然而&#xff0c;在如今的数字化时代&#xff0c;随着越来越多的企业将其文档存储和在线分享&#xff0c;pdf文件也可能面临安全隐私泄…

深入理解ADB:Android调试桥详解与使用指南

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a;Android ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言 正文 1. 什么是ADB&#xff1f; ADB的基本原理&#xff1a; 2. ADB的安装与配置 安装ADB工具集&#xff1a; 配置ADB环境变量&am…

人大金仓数据库驱动导入maven

1.去人大金仓官网去查找合适的驱动人大金仓-成为世界卓越的数据库产品与服务提供商 2.下载解压后 执行下面的代码 mvn install:install-file -DgroupIdkingbase -DartifactIdkingbase8 -Dversion8 -DfileF:\1foryou\foryou-report\kingbase8-8.6.0.jar -Dpackagingjar -Dgene…

FastAPI -- 第三弹(自定义响应、中间件、代理、WebSockets)

路径操作的高级配置 OpenAPI 的 operationId from fastapi import FastAPIapp FastAPI()# 通过 operation_id 参数设置 app.get("/items/", operation_id"some_specific_id_you_define") async def read_items():return [{"item_id": "F…

使用LVS+NGinx+Netty实现数据接入

数据接入 链接参考文档 LVSKeepalived项目 车辆数据上收&#xff0c;TBox通过TCP协议连接到TSP平台 建立连接后进行数据上传。也可借由该连接实现远程控制等操作。 通过搭建 LV—NGinx—Netty实现高并发数据接入 LVS&#xff1a;四层负载均衡&#xff08;位于内核层&#x…

Odoo17架构概述

多层架构 Odoo遵循多层架构&#xff0c;这意味着演示&#xff0c;业务逻辑和数据存储是分开的。更具体地说&#xff0c;它使用三层架构。 UI展示层 UI表示层是 HTML5、JavaScript 和 CSS 的组合。 应用程序的最顶层是用户界面。界面的主要功能是将任务和结果转换为用户可以理…

【数据结构】二叉树———Lesson2

Hi~&#xff01;这里是奋斗的小羊&#xff0c;很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~~ &#x1f4a5;&#x1f4a5;个人主页&#xff1a;奋斗的小羊 &#x1f4a5;&#x1f4a5;所属专栏&#xff1a;C语言 &#x1f680;本系列文章为个人学习…

Uniapp 组件 props 属性为 undefined

问题 props 里的属性值都是 undefined 代码 可能的原因 组件的名字要这样写&#xff0c;这个官方文档有说明

【Django】网上蛋糕商城后台-商品管理

1.商品管理功能 当管理员点击商品管理时&#xff0c;发送服务器请求 path(admin/goods_list/, viewsAdmin.goods_list), # 处理商品列表请求 def goods_list(request):try:type request.GET["type"]except:type 0try:ym request.GET["ym"]except:ym …

Spring Cloud Loadbalancer 的使用

一、默认负载均衡策略 Spring Cloud LoadBalancer 默认的负载均衡策略是轮询。 轮询效果示例 我们需要示例一个请求分发到不同的模块上&#xff0c;所以我们需要创建多模块项目。 新建 Spring Boot &#xff08;3.0.2&#xff09;的 Maven 项目&#xff08;JDK 17&#xff09…

ETL数据集成丨通过ETLCloud工具,将Oracle数据实时同步至Doris中

ETLCloud是一个全面的数据集成平台&#xff0c;专注于解决大数据量和高合规要求环境下的数据集成需求。采用先进的技术架构&#xff0c;如微服务和全Web可视化的集成设计&#xff0c;为用户提供了一站式的数据处理解决方案。 主要特点和功能包括&#xff1a; 实时数据处理&…

【已解决】Django连接MySQL启动报错Did you install mysqlclient?

在终端执行python manage.py makemigrations报错问题汇总 错误1&#xff1a;已安装mysqlclient&#xff0c;提示Did you install mysqlclient? 当你看到这样的错误信息&#xff0c;表明Django尝试加载MySQLdb模块但未找到&#xff0c;因为MySQLdb已被mysqlclient替代。 【解…

Linux——Shell脚本和Nginx反向代理服务器

1. Linux中的shell脚本【了解】 1.1 什么是shell Shell是一个用C语言编写的程序&#xff0c;它是用户使用Linux的桥梁 Shell 既是一种命令语言&#xff0c;有是一种程序设计语言 Shell是指一种应用程序&#xff0c;这个应用程序提供了一个界面&#xff0c;用户通过这个界面访问…

PyTorch 深度学习实践-处理多维特征的输入

视频指路 参考博客笔记 参考笔记二 通过多个线性模型来模拟非线性的空间变换&#xff0c;矩阵计算就是不同维度之间的空间转换 说明&#xff1a;1、乘的权重(w)都一样&#xff0c;加的偏置(b)也一样。b变成矩阵时使用广播机制。神经网络的参数w和b是网络需要学习的&#xff0c…

MybatisPlusException: Error: Method queryTotal execution error of sql 的报错解决

项目场景&#xff1a; 相关背景&#xff1a; 开发环境 开发系统时 系统页面加载正常 &#xff0c;发布运行环境后运行一段时间&#xff0c;前端页面 突然出现 报错信息&#xff0c; 报错信息如下&#xff1a; MybatisPlusException: Error: Method queryTotal execution erro…

如何在AWS上构建Apache DolphinScheduler

引言 随着云计算技术的发展&#xff0c;Amazon Web Services (AWS) 作为一个开放的平台&#xff0c;一直在帮助开发者更好的在云上构建和使用开源软件&#xff0c;同时也与开源社区紧密合作&#xff0c;推动开源项目的发展。 本文主要探讨2024年值得关注的一些开源软件及其在…

PDF转Word怎么快速转换?格式转换技巧分享

PDF文件和Word文档是我们日常工作中不可或缺的文件格式&#xff0c;同时文件之间的格式转换也十分常见。不同的格式有着不同的优点&#xff0c;将PDF文件改为Word文档后&#xff0c;在编辑或修改文件内容时更为方便。 下面小编就来给大家介绍几种常用的PDF转Word的转换方法&am…

Android 使用FFmpeg解析RTSP流,ANativeWindow渲染 使用SurfaceView播放流程详解

文章目录 ANativeWindow 介绍ANativeWindow 的主要功能和特点ANativeWindow 的常用函数工作流程原理图通过ANativeWindow渲染RGB纯色示例 播放RTSP流工作流程图关键步骤解析自定义SurfaceView组件native 层解码渲染 效果展示注意事项 这篇文章涉及到jni层&#xff0c;以及Ffmpe…

Linux-开机自动挂载(文件系统、交换空间)

准备磁盘 添加三块磁盘&#xff08;两块SATA&#xff0c;一块NVMe&#xff09; 查看设备&#xff1a; [rootlocalhost jian]# ll /dev/sd* [rootlocalhost jian]# ll /dev/nvme0n2 扩&#xff1a;查看当前主机上的所有块设备&#xff0c;通过如下指令实现&#xff1a; [root…

基于语音识别的会议记录系统

文章目录 核心功能页面展示使用技术方案功能结构设计数据库表展示 核心功能页面展示 视频展示功能 1.创建会议 在开始会议之前需要管理员先创建一个会议&#xff0c;为了能够快速开始会议&#xff0c;仅需填写会议的名称、会议举办小组、会议背景等简要会议信息即可成功创建。…