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://xiahunao.cn/news/3249680.html

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

相关文章

adb查看网卡信息,并修改网卡mac地址

这种方法修改mac后&#xff0c;关机后会失效! 文章结尾有永久修改mac地址的方法! 1. 查看网卡的信息&#xff0c;以及mac地址&#xff0c;ip地址&#xff0c;子网掩码等 //查看所有网卡信息adb shell ifconfig//MAC地址&#xff1a; HWaddr 5e:2c:e9:58:3e:4f //IP地址&a…

安全防御拓扑2

实验拓扑&#xff1a;​​​​​​​ 要求&#xff1a; 1、办公区设备可以通过电信链路和移动链路上网(多对多的NAT&#xff0c;并且需要保留一个公网IP不能用来转换) 2、分公司设备可以通过总公司的移动链路和电信链路访问到Dmz区的http服务器 3、多出口环境基于带宽比例进行…

Django定时任务框架django-apscheduler的使用

1.安装库 pip install django-apscheduler 2.添加 install_app django_apscheduler 3.在app下添加一个task.py文件&#xff0c;用来实现具体的定时任务 task.pydef my_scheduled_job():print("这个任务每3秒执行一次", time.time()) 4.在app下创建一个manag…

studio编译报错java.lang.NullPointerException

安卓studio编译报错&#xff0c;这个是一个新建的项目就报错&#xff0c;原因是 implementation androidx.appcompat:appcompat:1.7.0版本太高&#xff0c;修改后版本 implementation androidx.appcompat:appcompat:1.4.0&#xff0c; 编译又报错 18 issues were found wh…

【Node.js】初识 Node.js

Node.js 概念 Node.js 是一个开源与跨平台的 JavaScript运行时环境 &#xff0c;在浏览器外运行 V8 JavaScript 引擎(Google Chrome的内核)&#xff0c;利用事件驱动、非阻塞和异步输入输出 等技术提高性能。 可以理解为 Node.js就是一个服务器端的、非阻塞式 l/O 的、事件驱…

npm install时卡在sill idealTree buildDeps卡着不动

场景&#xff1a;做导出功能的时候要用上xlsx&#xff0c;正常npm install xlsx --save 问题描述&#xff1a;npm install时卡在sill idealTree buildDeps&#xff0c;&#xff0c;卡着不动 过程&#xff1a;在网上一顿百度试过好多种方法 1、切换taobao的镜像地址 npm conf…

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

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

设计分享—国外网站设计赏析

今天还是给大家分享一些国外的网站设计案例&#xff5e; 蓝蓝设计是一家专注而深入的界面设计公司&#xff0c;为期望卓越的国内外企业提供卓越的大数据可视化界面设计、B端界面设计、桌面端界面设计、APP界面设计、图标定制、用户体验设计、交互设计、UI咨询、高端网站设计、平…

来参与“向日葵杯”全国教育仿真技术大赛~

可点击进行了解&#xff1a;“向日葵杯”全国教育仿真技术大赛 (sunmooc.cn) 本次大赛共分为四个赛道&#xff1a;自主命题赛道、教育知识图谱设计赛道、FPGA硬件扑克牌对抗赛道、EasyAR元宇宙空间设计赛道。 参赛对象 &#xff1a; 具有正式学籍的在校研究生&#xff0c;本科…

Memcached介绍与使用

引言 本文是笔者对Memcached这个高性能分布式缓存组件的实践案例&#xff0c;Memcached是一种高性能的分布式内存对象缓存系统&#xff0c;用于减轻数据库负载&#xff0c;加速动态Web应用&#xff0c;提高网站访问速度。它通过在内存中缓存数据和对象来减少读取数据库的次数&…

Postman导出excel文件

0 写在前面 在我们后端写接口的时候&#xff0c;前端页面还没有出来&#xff0c;我们就得先接口测试&#xff0c;在此记录下如何使用postman测试导出excel接口。 如果不会使用接口传参可以看我这篇博客如何使用Postman 1 方法一 2 方法二 3 写在末尾 虽然在代码中写入文件名…

NVIDIA Container Toolkit 安装与配置帮助文档(Ubuntu,Docker)

NVIDIA Container Toolkit 安装与配置帮助文档(Ubuntu,Docker) 本文档详细介绍了在 Ubuntu Server 22.04 上使用 Docker 安装和配置 NVIDIA Container Toolkit 的过程。 概述 NVIDIA 容器工具包使用户能够构建和运行 GPU 加速容器。即可以在容器中使用NVIDIA显卡。 架构图如…

uniapp H5 如何根据接口返回form表单,跳转银联支付界面?

uniapp如何根据form表单&#xff0c;唤醒第三方支付? 文章目录 uniapp如何根据form表单&#xff0c;唤醒第三方支付?效果图实现 效果图 接口返回 form 表单数据 实现 // 例请求成功&#xff0c;返回数据 rechargePay({}).then(res > {// 接收接口返回数据let { result …

= null 和 is null;SQL中关于NULL处理的4个陷阱;三值逻辑

一、概述 1、NULL参与的所有的比较和算术运算符(>,,<,<>,<,>,,-,*,/) 结果为unknown&#xff1b; 2、unknown的逻辑运算(AND、OR、NOT&#xff09;遵循三值运算的真值表&#xff1b; 3、如果运算结果直接返回用户&#xff0c;使用NULL来标识unknown 4、如…

JRT实体视图查询

JRT的设计目标就是多数据库支持&#xff0c;对于爬行周边数据提供DolerGet解决爬取多维数据问题。但是对于通过父表字段筛选子表数据就不能通过DolerGet取数据了&#xff0c;因为查询到的父表数据没有子表数据的ID。 比如下面表&#xff1a; 我需要按登记号查询这个登记号的报…

【linux】服务器安装NVIDIA驱动

【linux】服务器安装NVIDIA驱动 【创作不易&#xff0c;求点赞关注收藏】&#x1f600; 文章目录 【linux】服务器安装NVIDIA驱动一、关闭系统自带驱动nouveau二、下载英伟达驱动三、安装英伟达驱动1、禁用X服务器和相关进程2、在TTY终端安装驱动3、验证是否安装成功4、重新启…

接口开发:Orcal数据库的批量修改sql

场景&#xff1a;在日常的CURD中一定会用到批量修改。在我们的项目中&#xff0c;使用的数据库是Orcal&#xff0c;由于之前基本都是使用Mysql的&#xff0c;使用的sql语句也基本都是用mysql的。但是在这次的接口编写时用mysql的批量修改出了问题&#xff0c;刚开始我还以为是写…

源码分析SpringCloud Gateway如何加载断言(predicates)与过滤器(filters)

我们今天的主角是Gateway网关&#xff0c;一听名字就知道它基本的任务就是去分发路由。根据不同的指定名称去请求各个服务&#xff0c;下面是Gateway官方的解释&#xff1a; Spring Cloud Gateway&#xff0c;其他的博主就不多说了&#xff0c;大家多去官网看看&#xff0c;只…

WDL(Wide Deep Learning for Recommender Systems)——Google经典CTR预估模型

一、文章简介 Wide & Deep Learning for Recommender Systems这篇文章介绍了一种结合宽线性模型和深度神经网络的方法&#xff0c;以实现推荐系统中的记忆和泛化。这种方法在Google Play商店的应用推荐系统中进行了评估&#xff0c;展示了其显著的性能提升。 推荐系统中的…

食堂采购系统开发:从需求分析到上线实施的完整指南

本篇文章&#xff0c;笔者将详细介绍食堂采购系统从需求分析到上线实施的完整过程&#xff0c;旨在为开发团队和管理者提供一个系统化的指南。 一、需求分析 1.用户需求 常见的需求包括&#xff1a; -采购计划管理 -供应商管理 -库存管理 -成本控制 -报表生成 2.系统功…