IT自学第三十八天

多线程


1、MybatisPlus简介

MybatisPlus

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

2、入门案例环境准备

入门案例

需求:基于资料中提供的mp-demo项目;改造为使用MP实现下列功能:

导入需要的项目,导入需要的数据库表,修改yaml文件的数据库连接信息。

3、快速入门

  • MyBatisPlus官方提供了starter,其中继承了Mybatis和MybatisPlus的所有功能,并且实现了自动装配效果。

代码演示:

XML 复制代码
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.3</version>
        </dependency>
  • 自定义的Mapper继承MybatisPlus提供的BaseMapper接口:

代码演示:

java 复制代码
public interface UserMapper extends BaseMapper<User> {

}

代码演示:

java 复制代码
@SpringBootTest
class UserMapperTest {

    @Autowired
    private UserMapper userMapper;

    @Test
    void testInsert() {
        User user = new User();
        user.setId(5L);
        user.setUsername("Lucy");
        user.setPassword("123");
        user.setPhone("18688990011");
        user.setBalance(200);
        user.setInfo("{\"age\": 24, \"intro\": \"英文老师\", \"gender\": \"female\"}");
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());
        userMapper.insert(user);
    }

    @Test
    void testSelectById() {
        User user = userMapper.selectById(5L);
        System.out.println("user = " + user);
    }


    @Test
    void testQueryByIds() {
        List<User> users = userMapper.selectBatchIds(List.of(1L, 2L, 3L, 4L));
        users.forEach(System.out::println);
    }

    @Test
    void testUpdateById() {
        User user = new User();
        user.setId(5L);
        user.setBalance(20000);
        userMapper.updateById(user);
    }

    @Test
    void testDeleteUser() {
        userMapper.deleteById(5L);
    }
}

对于多表查询,与复杂查询,利用手动写SQL执行。

4、常见注解

常见注解

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

  • 类名驼峰转下划线作为表名;
  • 名为id的字段作为主键;
  • 变量名驼峰转下划线作为表的字段名。

MybatisPlus中比较常见的几个注解如下:

5、常见配置

常见配置

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

6、条件构造器-QueryWrapper

条件构造器

MyBatisPlus支持各种复杂的where条件,可以满足日常开发的所有需求。

sql 复制代码
SELECT * FROM products;
UPDATE products SET price=99.9 WHERE id = 3
INSERT INTO products VALUES(3,12,1.2);
DELETE FROM name where ID = 4;

代码演示:

java 复制代码
    //查询user表的id,username,info,balance信息,且username带有o,balance>= 1000的信息
    @Test
    public void testQueryWrapper1(){
        //创建条件构造器
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        //查询的列
        queryWrapper.select("id","username","info","balance");
        //查询条件:名字带"o"的
        queryWrapper.like("username","o");
        //查询条件:balance >= 1000
        queryWrapper.ge("balance","1000");
        //查询
        List<User> userList = userMapper.selectList(queryWrapper);
        //输出
        for (User user : userList) {
            System.out.println(user);
        }
    }

    //更新用户名为jack的用户的余额为2000
    @Test
    public void testQueryWrapperUpdate(){
        User user = new User();
        user.setBalance(2000);
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username","jack");
        userMapper.update(user,queryWrapper);
    }

7、条件构造器-UpdateWrapper&LambdaQueryWrapper

基于UpdateWrapper的更新

需求:更新id为1,2,4的用户的余额,扣200.

代码演示:

java 复制代码
//    需求:更新id为1,2,4的用户的余额,扣200.
    @Test
    public void testUpdateWrapper(){
        UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
        //自定义更新的语句,设置的是set
        updateWrapper.setSql("balance = balance - 200");
        //id为1,2,4的用户
        updateWrapper.in("id",1,2,4);

        userMapper.update(null,updateWrapper);
    }

代码演示:

java 复制代码
    @Test
    public void testLambdaQueryWrapper1(){
        //创建条件构造器
        LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        //查询的列
        lambdaQueryWrapper.select(User::getId,User::getUsername,User::getInfo,User::getBalance);
        //查询条件:名字带"o"的
        lambdaQueryWrapper.like(User::getUsername,"o");
        //查询条件:balance >= 1000
        lambdaQueryWrapper.ge(User::getBalance,1000);
        //查询
        List<User> userList = userMapper.selectList(lambdaQueryWrapper);
        //输出
        for (User user : userList) {
            System.out.println(user);
        }
    }

8、自定义Sql

自定义SQL

我们可以利用MyBatisPlus的Wrapper来构建复杂的Where条件,然后自己定义SQL语句中剩下的部分。

需求:将id在指定范围的用户(例如1、2、4)的余额扣减指定值

代码演示:

java 复制代码
    //自定义拼接SQL
    @Test
    public void testCustomSqlSeqment(){
        LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.in(User::getId,1L,2L,4L);
        userMapper.updateBalanceByWrapper(200,lambdaQueryWrapper);
    }
java 复制代码
public interface UserMapper extends BaseMapper<User> {

    @Update("update user set balance = balance - ${amount} ${ew.customSqlSegment}")
    void updateBalanceByWrapper(@Param("amount") int amount, @Param("ew") LambdaQueryWrapper<User> queryWrapper);
}

9、Service接口-接口与类编写

Service接口

10、Service接口-案例基础

案例 基于Restful风格实现下列接口

需求:基于Restful风格实现下面的接口:

步骤:

  • 引入起步依赖
  • 定义UserController
  • 新增业务方法

特殊的业务方法,mybatisPlus中没有提供的;则可以自定义编写。

代码演示:

java 复制代码
@Api("用户接口管理")
@RestController
@RequestMapping("/users")
@RequiredArgsConstructor       //添加注释,不用添加@Autowired
public class UserController {

    private final IUserService userService;

    @ApiOperation("新增用户")
    @PutMapping
    public void saveUser(@RequestBody UserFormDTO userFormDto){
        //将userFormDto转换为User
        User user = BeanUtil.copyProperties(userFormDto, User.class);
        userService.save(user);
    }

    @ApiOperation("删除用户")
    @DeleteMapping("/{id}")
    public void deleteUser(@PathVariable("id") Long id){
        userService.removeById(id);
    }
}

11、Service接口-扣减余额

代码演示:

java 复制代码
    /**
     * 根据id扣减余额
     * @param id 用户id
     * @param amount  扣减的金额多少
     */
    @ApiOperation("根据id扣减余额")
    @PutMapping("/{id}/deduction/{amount}")
    public void updateBalanceById(@PathVariable Long id, @PathVariable Integer amount){
        userService.deductBalanceById(id,amount);
    }

    private final UserMapper userMapper;
    @Override
    public void deductBalanceById(Long id, Integer amount) {
        //1、判断用户是否存在
        User user = this.getById(id);
        if(user == null || user.getStatus() == 2){
            throw new RuntimeException("用户有问题");
        }
        //2、判断余额是否充足 ,当前用户的余额是否大于等于要扣除的金额
        if(user.getBalance() < amount){
            throw new RuntimeException("余额不足");
        }
        //3、扣减金额
        //update user set balance = balance - #{amount} where id = #{id}
        userMapper.deduceBalanceById(amount,id);
    }

    @Update("update user set balance = balance - #{amount} where id = #{id}")
    void deduceBalanceById(Integer amount, Long id);

12、IService的LambdaQuery方法应用

需求:

代码演示:

java 复制代码
    @ApiOperation("根据条件查询用户列表")
    @PostMapping("/list")
    public List<UserVO> queryList(@RequestBody UserQuery userQuery){
        String username = userQuery.getName();
        Integer status = userQuery.getStatus();
        Integer maxBalance = userQuery.getMaxBalance();
        Integer minBalance = userQuery.getMinBalance();
        List<User> userList = userService.lambdaQuery()
                .like(StrUtil.isNotBlank(username), User::getUsername, username)
                .eq(status != null, User::getStatus, status)
                .ge(minBalance != null, User::getBalance, minBalance)
                .le(maxBalance != null, User::getBalance, maxBalance)
                .list();  //最终进行查询
        return BeanUtil.copyToList(userList, UserVO.class);
    }

13、IService的LambdaUpdate方法应用

案例IService的Lambda更新

代码演示:

java 复制代码
        //3、扣减金额
        //update user set balance = balance - #{amount} [,status = 2] where id = #{id}
        int remainBalance = user.getBalance() - amount;
        this.lambdaUpdate()
                .set(User::getBalance, remainBalance)
                .set(remainBalance == 0, User::getStatus, 2)
                .eq(User::getId, id)
                .update();

14、批量插入数据的优化

案例:IService批量新增

代码演示:

java 复制代码
    //批量新增十万条数据
    @Test
    public void testBatch(){
        //记录开始时间与结束时间
        long start = System.currentTimeMillis();
        List<User> list = new ArrayList<>(1000);
        for(int i = 1; i <= 100000; i++) {
            list.add(buildUser(i));
            if(i % 1000 == 0){
                userService.saveBatch(list);
                list.clear();
            }
        }
        //记录技术时间
        long end = System.currentTimeMillis();
        System.out.println(end - start);
    }
相关推荐
Scott9999HH8 小时前
【IIoT流量实战】蒸汽管道阀门全关却仍有流量?用 Python 实现涡街信号 FFT 频谱分析与温压全补偿积算网关,深度拆解靠谱的涡街流量计厂家硬核技术标准
开发语言·python
腻害兔8 小时前
【若依项目-产品经理视角】深度拆解 RuoYi-Vue-Pro 商城模块:从商品管理到交易引擎,50 张表撑起一整套电商系统
java·大数据·vue.js·产品经理·ai编程
码智社9 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
AI云海9 小时前
python 列表、元组、集合和字典
开发语言·python
萧瑟余晖10 小时前
JDK 26 新特性详解
java·开发语言
马优晨11 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
人邮异步社区12 小时前
怎么把C语言学到精通?
c语言·开发语言
心平气和量大福大13 小时前
C#-WPF-控件-TextBox 数据绑定
开发语言·c#·wpf
ttwuai13 小时前
Cursor 生成 CRUD 后,Go 后台接口别只测 200:JWT、RBAC 和 tenant_id 怎么验
开发语言·后端·golang
维天说13 小时前
CLI-Switch 2026年3月版历史设计:Hook、TTY 隔离与 JSON 状态
java·服务器·json