Mybatis-plus的初始

1.简介

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

mybatis-plus 对 mybatis 做封装

2.特性

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑

  • 损耗小:启动即会自动注入基本 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 操作智能分析阻断,也可自定义拦截规则,预防误操作

3.支持数据库

任何能使用 mybatis 进行 CRUD, 并且支持标准 SQL 的数据库,具体支持情况如下,如果不在下列表查看分页部分教程 PR 您的支持。

  • mysql,oracle,db2,h2,hsql,sqlite,postgresql,sqlserver,Phoenix,Gauss ,clickhouse,Sybase,OceanBase,Firebird,cubrid,goldilocks,csiidb

  • 达梦数据库,虚谷数据库,人大金仓数据库,南大通用(华库)数据库,南大通用数据库,神通数据库,瀚高数据库

5.主流的ORM持久层框架

  • Mybatis

    • SQL语句可以自由控制,更加灵活,性能较高

    • SQL代码分离,阅读和维护。

    • 提供XML标签,之前编写动态SQL语句。

  • JPA

    • JPA移植性好

    • 提供很多CURD的方法,提高开发效率

    • 对象话程度较高

  • mybatis缺点

    • 简单CURD操作可能还需要我们自己去的编写SQL语句

    • XML有大量的SQL要维护

    • Mybatis自身的功能有限,但支持插件Plugin

这些mybatis问题如何解决呢?Mybatis-plus

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

 

实战:

02、创建项目springboot +maven

01、依赖配置

<!--lombok依赖,可以辅助项目的开发比如生成setter.getter和日志-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--mybatis依赖-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.2</version>
</dependency>
<!--mysql驱动依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.26</version>
</dependency>

02、在application.yml中配置数据源

# 配置数据库连接
spring:
datasource:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/kss-web-db?serverTimezone=GMT%2b8&useUnicode=true&characterEncoding=utf-8&useSSL=false
username: root
password: mkxiaoer

03、创建实体

package com.kuangstudy.entity;

import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;
import java.util.Date;

/**
* @author 飞哥
* @Title: 学相伴出品
* @Description: 飞哥B站地址:https://space.bilibili.com/490711252
* 记得关注和三连哦!
* @Description: 我们有一个学习网站:https://www.kuangstudy.com
* @date 2021/11/10 21:03
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@TableName("kss_user") // 指定实体和数据库表kss-user做映射
public class User extends Model<User> implements java.io.Serializable {
// 用户id
@TableId(type = IdType.AUTO)
private Integer id;
// 用户昵称
private String nickname;
// 用户密码
private String password;
// 用户收集
private String telephone;
// 用户的邮箱
private String email;
// 用户的头像
private String avatar;
// 用户的签名
private String sign;
// 创建时间
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
// 更新时间
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
// 用户的激活状态 1激活 0 未激活
private Integer active;
// 角色 admin 管理员 normal正常用户
private String role;
}

04、新建一个Mapper

package com.kuangstudy.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.kuangstudy.entity.User;
import org.springframework.stereotype.Repository;


@Repository
public interface UserMapper extends BaseMapper<User> {

}

05、扫包

package com.kuangstudy.config.mybatis;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

//Spring boot方式
@Configuration
@MapperScan("com.kuangstudy.mapper")
public class MybatisPlusConfig {

// 最新版
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
//设置最大单页限制数量,默认 500 条,-1 不受限制
paginationInnerInterceptor.setMaxLimit(500L);
interceptor.addInnerInterceptor(paginationInnerInterceptor);
return interceptor;
}


}

03、为什么要继承BaseMapper

package com.kuangstudy.mapper;


import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.kuangstudy.entity.User;
import org.springframework.stereotype.Repository;




@Repository
public interface UserMapper extends BaseMapper<User> {


}

BaseMapper<User> 代表的是:只要有UserMapper继承了BaseMapper那么就自动拥有父类提供的能力。

一个类继承另外一个类作用:职责分担。

04、Mybatis-plus的常用注解

package com.kuangstudy;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.kuangstudy.entity.Blog;
import com.kuangstudy.enums.StatusEnum;
import com.kuangstudy.entity.User;
import com.kuangstudy.mapper.BlogMapper;
import com.kuangstudy.mapper.UserMapper;
import com.kuangstudy.service.user.IUserService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;


import javax.annotation.Resource;
import java.util.List;


@SpringBootTest
class KssWebProjectApplicationTests {


    @Autowired
    private UserMapper userMapper;
    @Test
    public void testSelect() {
        List<User> users = userMapper.selectList(null);
        users.forEach(System.out::println);
    }


}

 执行打印的sql语句如下:

SELECT id,nickname,password,telephone,email,avatar,sign,create_time,update_time,active,role FROM kss_user

实体如下

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class KssUser extends Model<KssUser> implements java.io.Serializable {
    // 省略代码
}

从这里分析得出:mybatis-plus底层会根据实体的名字,自动变成小写,然后通过反射找到实体中所有的属性,然后拼接成SQL语句:

1.如果表名和实体不一致:统一指定,省去不必要的麻烦

@TableName("数据表")

2.如果属性和数据库的字段不一致:

@TableField("数据字段")

05、排除非表字段的三种方式(重点)

在开发中往往有时候,在开发的时候,在实体bean中增加一些额外的字段,但是这些字段只是去存储一些数据,但是不是数据库表的列。那么就告诉MP进行排除。

如果不排除你觉得会怎么样?

它就会把它当做SQL的一部分去自动拼接上,肯定是不对的

排除方式1:transient

// 临时字段
private transient String remark;

排除方式2:static

// 临时字段
private static String remark;

排除方式3:@TableField(exist = false)(==推荐==)

@TableField(exist = false)
private String remark;
  • static有一个问题,转换json的时候或者你要远程传递的属性的属性会排除在外

  • transient 被这个关键字修饰的字段,代表不会序列化到流中进行传递。比如:微服务RPC或者resttemplate传输的时候,被transient修饰的属性会自动忽略。

06、查询Wrapper

抽象父类:AbstractWrapper

查询Wrapper

  • QueryWrapper(如果多表关联查询用:QueryWrapper 为什么因为有别名的问题.)

  • LambdaQueryWrapper(==推荐==) 但是不万能?

更新Wrapper

  • UpdateWrapper

为什么没有InsertWrapper , 因为insert没有where条件

在开发中,除了根据id返回实体,还有多条件查询,关联查询,子查询等等。

一句话:AbstractWrapper是引来指定查询条件的类。

方法架构

得出结论:其实就给查询语句设置查询条件,的处理器。它把开发中所以的查询条件的规则都进行了封装

 

/**
     * 查询(根据 columnMap 条件)
     *
     * @param columnMap 表字段 map 对象
     */
    List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);


    /**
     * 根据 entity 条件,查询一条记录
     *
     * @param queryWrapper 实体对象封装操作类(可以为 null)
     */
    T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);


    /**
     * 根据 Wrapper 条件,查询总记录数
     *
     * @param queryWrapper 实体对象封装操作类(可以为 null)
     */
    Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);


    /**
     * 根据 entity 条件,查询全部记录
     *
     * @param queryWrapper 实体对象封装操作类(可以为 null)
     */
    List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);


    /**
     * 根据 Wrapper 条件,查询全部记录
     *
     * @param queryWrapper 实体对象封装操作类(可以为 null)
     */
    List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);


    /**
     * 根据 Wrapper 条件,查询全部记录
     * <p>注意: 只返回第一个字段的值</p>
     *
     * @param queryWrapper 实体对象封装操作类(可以为 null)
     */
    List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);


    /**
     * 根据 entity 条件,查询全部记录(并翻页)
     *
     * @param page         分页查询条件(可以为 RowBounds.DEFAULT)
     * @param queryWrapper 实体对象封装操作类(可以为 null)
     */
    <E extends IPage<T>> E selectPage(E page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);


    /**
     * 根据 Wrapper 条件,查询全部记录(并翻页)
     *
     * @param page         分页查询条件
     * @param queryWrapper 实体对象封装操作类
     */
    <E extends IPage<Map<String, Object>>> E selectMapsPage(E page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

01、传统的写法 定义一个接口:

package com.kuangstudy.mapper;


import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.kuangstudy.entity.User;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;


import java.util.List;




@Repository
public interface UserMapper {




    /**
     * 根据 entity 条件,查询一条记录
     */
    List<User> selectList(@Param("nickname") String username,
                          @Param("password")String password);


}

在UserMapper.xml定义如下:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.kuangstudy.mapper.UserMapper">




    <select id="selectList" resultType="com.kuangstudy.entity.User">
           select * from kss_user where nickname = #{nickname} and password = #{password}
    </select>


</mapper>

使用Mybatis-plus写法

public List<User> findUserList(String username,String password){
        //QueryWrapper负责查询条件的和排序的类
        //where nickname = #{nickname} and password = #{password}
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("nickname",username);
        queryWrapper.eq("password",password);
        // 2:执行sql拼接条件
        // userMapper.selectList是来自己与BaseMapper<User>
        // 反射实体转换成User.class通过反射拿到它里面所有的属性拼接sql语句, select id,nickname,password where nickname='yykk' and password='12121545'
        List<User> list = userMapper.selectList(queryWrapper);
        return list;
    }

执行的SQL如下:

==>  Preparing: SELECT id,nickname,password,telephone,email,avatar,sign,create_time,update_time,active,role FROM kss_user WHERE (nickname = ? AND password = ?)
==> Parameters: yykk(String), 8c953f1d3dcb49afd4f3d365627149fd(String)

上面存在的问题

queryWrapper.eq("nickname",username);
queryWrapper.eq("password",password);

1、"nickname" 到底是数据库的列呢?还是实体的属性呢?

2、"nickname"很多时候会写错,但是开发者就不会往这里思考?

如何解决问题呢?

用LambdaQueryWrapper来解决这个问题

public List<User> findUserList2(String username,String password){
        //QueryWrapper负责查询条件的和排序的类
        //where nickname = #{nickname} and password = #{password}
        LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<User>();
        lambdaQueryWrapper.eq(User::getNickname,username);
        lambdaQueryWrapper.eq(User::getPassword,password);
        // 2:执行sql拼接条件
        // userMapper.selectList是来自己与BaseMapper<User>
        // 反射实体转换成User.class通过反射拿到它里面所有的属性拼接sql语句, select id,nickname,password where nickname='yykk' and password='12121545'
        List<User> list = userMapper.selectList(lambdaQueryWrapper);
        return list;
    }

07、动态SQL

就是开发中,如果条件满足就拼接条件,如果不满足不拼接。这种动态SQL其实一般应用在:后台的这种复杂的SQL查询。

需求:

1:根据用户名模糊查询用户信息 username like '%xxx%'

2:并且查询出激活的用户 active = 1

3:并且查询角色等于超级管理员 role=admin

4:查询出注册时间在某个时间段的:create_time betwwend starttime and endtime;

注意:默认情况下查询的所有的用户,只有用户操作了才开始拼接条件.

实现步骤

1、查询所有数据,摒弃所有的条件,先把业务做通。

2、建设一个查询条件的vo,不要传递整个实体。

01、第一种实现方案 - 原生的实现方案Mybatis+Xml来实现

用这种方案就告诉你一个道理:MP支持原生的mybatis+xml的方式。

实现步骤如下:

1:定义mp配置支持mybatis原生的xml文件的机制

# mybatis-plus的配置
mybatis-plus:
  configuration:
    # 开启mybatis日志执行sql打印
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    call-setters-on-nulls: true
    default-enum-type-handler: org.apache.ibatis.type.EnumOrdinalTypeHandler
  # 重点:告诉mybatis你的mapper.xml文件在那个位置,我会启动的过程找到这个配置文件进行加载  
  mapper-locations: classpath*:/mapper/*.xml
  # 别名映射,不建议使用,简写的东西往往很多麻烦的事情,写错了你都知道。告诉你在xml文件中只要是这个包下面的实体,你都用类名小写,省去书写的工作。
  type-aliases-package: com.kuangstudy.entity
  type-enums-package: com.kuangstudy.enums

2:定义一个接口方法

package com.kuangstudy.mapper;


import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.kuangstudy.entity.User;
import com.kuangstudy.vo.UserParamVo;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;


import java.util.List;




@Repository
public interface UserMapper extends  BaseMapper<User> {




    /**
     * 根据userParamVo查询对应的用户信息
     * @param userParamVo
     * @return
     */
    public List<User> findUsers(UserParamVo userParamVo);


}

UserMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.kuangstudy.mapper.UserMapper">




    <select id="findUsers" resultType="com.kuangstudy.entity.User" parameterType="com.kuangstudy.vo.UserParamVo">
        SELECT
            id,
            nickname,
            PASSWORD,
            telephone,
            email,
            avatar,
            sign,
            create_time,
            update_time,
            active,
            role
        FROM
            kss_user
        <where>
            <if test="username!=null and username!=''">
                AND  nickname LIKE #{username}
            </if>
            <if test="active!=null">
                AND active = #{active}
            </if>
            <if test="role!=null and role!=''">
                AND role = #{role}
            </if>
        </where>


    </select>




</mapper>
@Test
    public void testSelectMybatisSQL() throws JsonProcessingException {
        // 1: 设置条件
        UserParamVo userParamVo = new UserParamVo();
        userParamVo.setUsername("yykk1");
        userParamVo.setActive(1);
        userParamVo.setRole("admin");
        List<User> userList = userMapper.findUsers(userParamVo);
        userList.forEach(System.out::println);
    }

02、第二种实现方案 - 实现方案MP+LambdaQueryWrapper来实现

用这种方案就告诉你一个道理:MP它很优秀确实可以帮做到单表的动态SQL查询,用一种面向对象的方式。

public List<User> findUserList2(UserParamVo userParamVo) {
        //QueryWrapper负责查询条件的和排序的类
        LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<User>();
        lambdaQueryWrapper.eq(Optional.ofNullable(userParamVo.getActive()).isPresent(), User::getActive, userParamVo.getActive());
        lambdaQueryWrapper.eq(Optional.ofNullable(userParamVo.getRole()).isPresent(), User::getRole, userParamVo.getRole());
        lambdaQueryWrapper.like(!StringUtils.isEmpty(userParamVo.getUsername()), User::getNickname, userParamVo.getUsername());
        // 2:执行sql拼接条件
        lambdaQueryWrapper.orderByDesc(User::getCreateTime);
        // userMapper.selectList是来自己与BaseMapper<User>
        // 反射实体转换成User.class通过反射拿到它里面所有的属性拼接sql语句, select id,nickname,password where nickname='yykk' and password='12121545'
        List<User> list = userMapper.selectList(lambdaQueryWrapper);
        return list;
    }

03、第三种实现方案 - 采用Mybatis的Mapper+XML+LambdaQueryWrapper/QueryMapper来实现

用这种方案就告诉你一个道理:MP它很优秀,但是它不是万能的,复杂的关联查询是无能无能力。因为默认的BaserMapper值提供了一些单表常用,多表关联查询就必须还是得自己去编写SQL语句,进行混合使用,。当然你也可以不用,全部原生的写法。

01、使用原生的XML来完成

Mapper接口

package com.kuangstudy.mapper;


import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.kuangstudy.entity.User;
import com.kuangstudy.vo.UserParamVo;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;


import java.util.List;
import java.util.Map;




@Repository
public interface UserMapper extends  BaseMapper<User> {


     List<Map<String,Object>> findBlogsUsers();


}

xml文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.kuangstudy.mapper.UserMapper">




    <select id="findBlogsUsers" resultType="java.util.Map">
            SELECT
                ku.*,
                count( 1 ) AS num
            FROM
                kss_blog kb
                LEFT JOIN kss_user ku ON kb.user_id = ku.id
            GROUP BY kb.user_id
            ORDER BY num DESC
    </select>




</mapper>

测试

//关联查询 + Mybatis+xml
    @Test
    public void testSelectMybatisSQL3() throws JsonProcessingException {
        List<Map<String,Object>> userList = userMapper.findBlogsUsers();
        userList.forEach(System.out::println);
    }

返回map一定要特别的小心取值问题,因为map的key是直接根据你表的列名进行设定的

map.get("createTime")而是map.get("create_time");

上面存在一个问题

分页必须自己去写,很繁琐,

02、使用MpQueryMapper来完成分页

导入分页插件

package com.kuangstudy.config.mybatis;


import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.pagination.optimize.JsqlParserCountOptimize;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


//Spring boot方式
@Configuration
@MapperScan("com.kuangstudy.mapper")
public class MybatisPlusConfig {


    // 最新版
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
        //设置最大单页限制数量,默认 500 条,-1 不受限制
        paginationInnerInterceptor.setMaxLimit(500L);
        interceptor.addInnerInterceptor(paginationInnerInterceptor);
        return interceptor;
    }




}

03、使用关联查询 +QueryMapper来完成分页

分析

userMapper.selectPage(page,wrapper)

上面这个分页查询方法,只能针对当前自己的实体,它很好支持和处理,但是关联查询就不行。

  • 上面代码的底层:会通过拦截器PageIntercetor进行拦截处理会把执行sql和求count自动发起和执行

  • 同时根据返回的总数,字段换算出来pages,total,current,

  • 数据放在 records中

  • 用Page整个包裹返回

规律

  • sql (自动通过反射去生成)

  • 分页条件

  • page

04、如果关联查询呢?只不过sql语句自己去写

  • sql (自己通过mapper.xml)文件自己去写

  • 分页条件(用mp)

  • page(用mp)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值