CGB2109-Day14-MybatisPlus

本文详细介绍了MyBatisPlus(MP)的介绍、特点、ORM思想,以及一系列入门和实战案例,包括对象关系映射、CRUD操作、条件构造器、动态SQL、分页插件等。此外,还展示了商品分类业务模块的实现,包括路由跳转、数据结构设计和查询方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. MybatisPlus(MP)

1.1 MP介绍

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

1.2 MP特点

无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
内置性能分析插件:可输出 SQL 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作

1.3 ORM思想

1.3.1 ORM说明

对象关系映射(英语:Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序设计技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换。从效果上说,它其实是创建了一个可在编程语言里使用的“虚拟对象数据库”。如今已有很多免费和付费的ORM产品,而有些程序员更倾向于创建自己的ORM工具。

总结:以面向对象的方式操作数据库

1.3.2 ORM特点

  1. 对象与数据库中的表什么关系? 一一映射
  2. 对象中的属性与数据库中的字段什么关系? 一一映射
  3. 以面向对象的方式操作数据库。由框架动态生成Sql语句。实现了跨数据库的操作。

1.4 MP入门案例

1.4.1 导入jar包

<!--spring整合mybatis-plus -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.3</version>
        </dependency>

1.4.2 编辑POJO对象

在这里插入图片描述

1.4.3 编辑Mapper接口

说明: MP将常用的CURD操作进行封装.以后用户需要使用,只需要继承公共的业务接口即可.
在这里插入图片描述

1.4.4 编辑YML文件

在这里插入图片描述

1.4.5 入门案例

package com.jt;

import com.jt.mapper.UserMapper;
import com.jt.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.Date;

@SpringBootTest
class JtApplicationTests {

    @Autowired
    private UserMapper userMapper;

    /**
     * 实现数据新增
     */
    @Test
    void contextLoads() {
        User user = new User();
        user.setUsername("admin888")
                .setPassword("123456")
                .setEmail("11@qq.com")
                .setPhone("13445671234")
                .setStatus(true)
                .setCreated(new Date())
                .setUpdated(user.getCreated());
        int rows = userMapper.insert(user);
        System.out.println("影响的行数:"+rows);
    }

}

1.5 MP案例

1.5.1 根据ID查询

/**
     * 案例1: 根据ID进行查询
     */
    @Test
    public void test01(){
        int id = 1;
        User user = userMapper.selectById(id);
        System.out.println(user);
    }

1.5.2 对象封装数据

/**
     * /* //如果查询的结果不能保证 则使用list集合接收
     * List<User> userList = userMapper.selectList(null)/
     * 根据其它属性进行查询
     * 根据username="admin110" 进行查询
     * 组件: 条件构造器  用来封装where条件的.
     * Sql: select * from user where username="admin110"
     * 方式1: 利用对象封装数据
     */
    @Test
    public void test02(){
        User temp = new User();
        temp.setUsername("admin119"); //=号操作
        //条件构造器,会根据对象中不为null的元素动态拼接Sql
        QueryWrapper<User> queryWrapper = new QueryWrapper<>(temp);
        //如果可以保证查询的结果只有一个
        User user = userMapper.selectOne(queryWrapper);
        System.out.println(user);
    }

1.5.3 转译字符方式

 /**
     * 需求: 查询ID > 5的用户
     * Sql: select * from user where id > 5
     * 转译字符:  >  gt, < lt, = eq
     *          >=  ge, <=le  != ne
     * 方式2: 利用逻辑运算符 实现Sql操作
     */
    @Test
    public void test03(){
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.gt("id",5);
        List<User> userList = userMapper.selectList(queryWrapper);
        System.out.println(userList);
    }

1.5.4 模糊查询

/**
     * 需求: 查询username 包含admin的数据,并且按照id降序排列
     * Sql: select * from user where username like "%admin%" order by id desc
     * 知识点:
     *  1. like      "%admin%"      左右都有%号
     *  2. likeLeft  "%admin"       左边有%号
     *  3. likeRight "admin%"       左边有%号
     */
    @Test
    public void test04(){
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.like("username","admin")
                    .orderByDesc("id");
        List<User> userList = userMapper.selectList(queryWrapper);
        System.out.println(userList);
    }

1.5.5 in关键字

/**
     * 需求: 查询id=1,2,23,24的数据
     * Sql: select * from user where id in (1,2,23,24)
     * 注意事项: 使用in关键字时,最好使用包装类型.
     */
    @Test
    public void test05(){
        Integer[] ids = {1,2,23,24};
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("id",ids);
        //方式1: 利用条件构造器查询
        List<User> userList = userMapper.selectList(queryWrapper);
        System.out.println(userList);
        //方式2: 利用API查询
        List list = Arrays.asList(ids);
        List<User> userList2 = userMapper.selectBatchIds(list);
        System.out.println(userList2);
    }

1.5.6 动态Sql查询

 /**
     * 需求: 动态查询数据,利用电话/邮箱查询数据
     * 疑问: MP特点 根据对象(POJO)中不为null的属性充当条件
     * API:
     *      eq(boolean true 拼接/false 不拼接, R column, Object val)
     *      StringUtils.hasLength(phone)
     */
    @Test
    public void test06(){
        String phone = "13111112222";
        String email = "";
        QueryWrapper<User> queryWrapper = new QueryWrapper();
        queryWrapper.eq(StringUtils.hasLength(phone), "phone",phone)
                    .eq(StringUtils.hasLength(email), "email",email);
        List<User> list = userMapper.selectList(queryWrapper);
        System.out.println(list);
    }

1.5.7 根据主键查询

/**
     * 条件: 只查询主键信息
     * API: selectObjs: 获取主键信息
     * 实际用途:
     *      进行关联查询
     */
    @Test
    public void test07(){
        List ids = userMapper.selectObjs(null);
        System.out.println(ids);
    }

1.5.8 根据主键更新

 /**
     * 需求:用户的修改操作
     * 1. 根据ID修改数据
     *      将id=22 的name改为 admin110,phone="110110"
     *    原理: Id当作唯一where条件. 其它不为null的属性当作set条件
     *    userMapper.updateById(user);
     */
    @Test
    public void test08(){
        User user = new User();
        user.setId(22).setUsername("admin110").setPhone("110110");
        userMapper.updateById(user);
        System.out.println("更新成功!!!");
    }

1.5.9 根据其它条件更新

/**
     * 需求:用户的修改操作
     *     要求将password=123456的phone改为10086,email: 10086@qq.com
     * 参数说明:
     *      1.entity: 主要的目的封装set条件
     *      2.wrapper: 封装修改条件的条件构造器
     */
    @Test
    public void test09(){
        User user = new User();
        user.setPhone("10086").setEmail("10086@qq.com");
        UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("password","123456");
        userMapper.update(user,updateWrapper);
    }

2. 实现商品分类业务模块

2.1 路由跳转页面

需求: 当用户点击商品分类时,应该跳转到商品分类页面中.
在这里插入图片描述
编辑路由文件
在这里插入图片描述

2.2 商品分类层级代码搭建

2.2.1 编辑POJO

/**
 * @author 刘昱江
 * 时间 2021/3/26
 */
@Data
@Accessors(chain = true)
@TableName("item_cat")
public class ItemCat extends BasePojo{

    @TableId(type = IdType.AUTO) //主键自增
    private Integer id;         //定义主键
    private Integer parentId;   //定义父级菜单 开启驼峰规则映射
    private String name;        //分类名称
    private Boolean status;     //分类状态 0 停用 1 正常
    private Integer level;      //商品分类等级  1 2 3
    @TableField(exist = false)   //当前属性不参与MP操作
    private List<ItemCat> children; //是业务数据 不是数据库字段
}

2.2.2 搭建层级代码

在这里插入图片描述

2.3 商品分类业务说明(难点知识!!!)

2.3.1 表设计

在这里插入图片描述

2.3.2 数据结构设计

一级/二级一定有children/ 三级的children为null
在这里插入图片描述

2.4 商品分类列表展现

2.4.1 业务接口说明

  • 请求路径: /itemCat/findItemCatList/{level}
  • 请求类型: get
  • 请求参数: level
参数名称参数说明备注
level查询级别1查询一级分类 2查询1-2 级商品分类 3查询1-2-3级商品分类
  • 业务说明: 查询3级分类菜单数据 要求三层结构嵌套
  • 返回值: SysResult对象
参数名称参数说明备注
status状态信息200表示服务器请求成功 201表示服务器异常
msg服务器返回的提示信息可以为null
data服务器返回的业务数据3级商品分类信息

2.4.2 页面URL说明

在这里插入图片描述

2.4.3 编辑ItemCatController

package com.jt.controller;

import com.jt.pojo.ItemCat;
import com.jt.service.ItemCatService;
import com.jt.vo.SysResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@CrossOrigin
@RequestMapping("/itemCat")
public class ItemCatController {

    @Autowired
    private ItemCatService itemCatService;

    /**
     * 需求: 查询三级商品分类信息
     * URL地址: /itemCat/findItemCatList/{level}
     * 参数:    level  1/2/3
     * 返回值:  SysResult(三级菜单)
     */
    @GetMapping("/findItemCatList/{level}")
    public SysResult findItemCatList(@PathVariable Integer level){
        List<ItemCat> catList = itemCatService.findItemCatList(level);
        return SysResult.success(catList);
    }
}

2.4.4 升级MPjar包

<!--spring整合mybatis-plus -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.3</version>
        </dependency>

2.4.5 编辑ItemCatService

package com.jt.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jt.mapper.ItemCatMapper;
import com.jt.pojo.ItemCat;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class ItemCatServiceImpl implements ItemCatService{

    @Autowired
    private ItemCatMapper itemCatMapper;

    /**
     * 只查询一级菜单  parent_id=0 或者 level=1
     * 查询二级菜单信息 parent_id = 一级ID
     * 查询三级菜单信息 parent_id = 二级ID
     * 思考: 如何优化代码   要求查询时间最好 控制在20ms+-
     * @param level
     * @return
     */
    @Override
    public List<ItemCat> findItemCatList(Integer level) {
        long startTime = System.currentTimeMillis();
        QueryWrapper<ItemCat> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("parent_id",0);
        List<ItemCat> oneList = itemCatMapper.selectList(queryWrapper);
        for (ItemCat oneItemCat : oneList){
            //获取一级对象的ID
            int oneId = oneItemCat.getId();
            //清空多余的条件
            queryWrapper.clear();
            //查询二级数据
            queryWrapper.eq("parent_id",oneId);
            List<ItemCat> twoList = itemCatMapper.selectList(queryWrapper);
            //获取3级菜单信息
            for(ItemCat twoItemCat : twoList){
                int twoId = twoItemCat.getId();
                queryWrapper.clear();
                queryWrapper.eq("parent_id",twoId);
                List<ItemCat> threeList = itemCatMapper.selectList(queryWrapper);
                //将三级数据封装到二级对象中
                twoItemCat.setChildren(threeList);
            }
            //将二级封装到一级对象中
            oneItemCat.setChildren(twoList);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("业务调用耗时:"+(endTime - startTime)+"毫秒");
        return oneList;
    }
}

2.4.6 页面效果展现

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

闪耀太阳

感觉文章不错的记得打赏呀

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值