SpringBoot——MyBatis-Plus源码分析及开发实践详解

news2025/2/21 4:44:13

focus w x:CodingTechWork

文章目录

      • focus w x:`CodingTechWork`
  • 引言
  • MyBatis-Plus 介绍
    • 概述
    • 特点
    • 常用注解
      • @TableName
      • @TableId
        • IdType类型
    • @TableField
  • MyBatis-Plus 源码分析
    • IService原生CURD接口
      • save
      • saveorUpdate
      • remove
      • update
      • get
      • list
      • page
    • Mapper原生CURD接口
      • insert
      • delete
      • update
      • select
      • page
    • 自动分页
      • 原理
      • PaginationInnerInterceptor源码
      • ParameterUtils
    • lambda函数
      • Compare接口源码
      • Func接口源码
      • Join接口源码
      • Nested接口源码
      • 常用函数总结
  • MyBatis-Plus 代码实践
    • 依赖
    • 分页插件配置
    • IDEA插件MyBatisPlus
    • 类模板
      • entity类
      • mapper类
      • service接口类
      • service实现类
    • lambda表达式
      • LambdaQueryWrapper查询
      • QueryWrapper查询
      • lambdaUpdate更新
    • Mapper结合xml文件查询
      • 根据基本数据类型查询
        • mapper方法
        • DemoEntityMapper.xml文件
      • 根据多个参数查询
        • mapper方法
        • DemoEntityMapper.xml文件
      • 根据对象参数查询
        • mapper方法
        • DemoEntityMapper.xml文件
      • 分页查询
        • mapper方法
        • DemoEntityMapper.xml文件
        • 调用代码

引言

  在上一家公司一直使用Spring Data JPA,它是对基于JPA的数据访问层的增强支持,底层使用Hibernate框架,支持使用原生SQL或JPQL查询语言。JPA是基于ORM的,它把代码和DB分离,即在代码和DB之间增加了新的一层,从而间接操作DB,大家可能觉得这个学习成本比较高,但其实也还好,都用不到xml文件等。
  而在新的公司,使用的是MybatisMybatis面向DB基于SQL的模式,复杂的SQL需要通过mapperxml文件来操作DB可能更直观友好,当Mybatis结合Mybatis-Plus就原地起飞了。本文主要总结使用Mybatis-Plus的一些实践经验及源码分析。

MyBatis-Plus 介绍

概述

  MyBatis-PlusMybatis的增强工具,可以简化开发,提高我们的开发效率。

特点

  1. 无侵入:是Mybatis的增强工具,不做侵入式改变。
  2. 丰富的lambda调用支持:通过Lambda表达式编写各类查询。
  3. 强大的CRUD操作支持:内置MapperIService接口和各种操作方法。
  4. 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作。
    … …

常用注解

@TableName

描述:表名注解,标识实体类。

@TableId

描述:主键注解

IdType类型

说明
AUTO数据库ID自增
NONE默认,无状态,该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT)
INPUTinsert 前自行 set 主键值
ASSIGN_ID分配 ID(主键类型为 Number(Long 和 Integer)或 String)(since 3.3.0),使用接口IdentifierGenerator的方法nextId(默认实现类为DefaultIdentifierGenerator雪花算法)
ASSIGN_UUID分配 UUID,主键类型为 String(since 3.3.0),使用接口IdentifierGenerator的方法nextUUID(默认 default 方法)
ID_WORKER分布式全局唯一 ID 长整型类型(please use ASSIGN_ID)
UUID32 位 UUID 字符串(please use ASSIGN_UUID)
ID_WORKER_STR分布式全局唯一 ID 字符串类型(please use ASSIGN_ID)

@TableField

描述:字段注解(非主键)
常用属性:

属性类型 必须指定 默认值 描述
valueString 否 “” 数据库字段名
existboolean 否 true 是否为数据库表字段

MyBatis-Plus 源码分析

IService原生CURD接口

save

// 插入一条记录(选择字段,策略插入)
boolean save(T entity);
// 插入(批量)
boolean saveBatch(Collection<T> entityList);
// 根据插入批次数量,插入(批量)
boolean saveBatch(Collection<T> entityList, int batchSize);

saveorUpdate

// TableId 注解存在更新记录,是否插入一条记录或者更新记录
boolean saveOrUpdate(T entity);
// 根据updateWrapper尝试更新,否继续执行saveOrUpdate(T)方法
boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper);
// 批量修改插入
boolean saveOrUpdateBatch(Collection<T> entityList);
// 根据插入批次数量,批量修改插入
boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize);

remove

// 根据 entity 条件,删除记录
boolean remove(Wrapper<T> queryWrapper);
// 根据 ID 删除
boolean removeById(Serializable id);
// 根据 columnMap 条件,删除记录
boolean removeByMap(Map<String, Object> columnMap);
// 删除(根据ID 批量删除)
boolean removeByIds(Collection<? extends Serializable> idList);

update

// 根据 UpdateWrapper 条件,更新记录 需要设置sqlset
boolean update(Wrapper<T> updateWrapper);
// 根据 whereWrapper 条件,更新记录
boolean update(T updateEntity, Wrapper<T> whereWrapper);
// 根据 ID 选择修改
boolean updateById(T entity);
// 根据ID 批量更新
boolean updateBatchById(Collection<T> entityList);
// 根据插入批次数量,根据ID 批量更新
boolean updateBatchById(Collection<T> entityList, int batchSize);

get

// 根据 ID 查询
T getById(Serializable id);
// 根据 Wrapper,查询一条记录。结果集,如果是多个会抛出异常,随机取一条加上限制条件 wrapper.last("LIMIT 1")
T getOne(Wrapper<T> queryWrapper);
// 根据 Wrapper,查询一条记录
T getOne(Wrapper<T> queryWrapper, boolean throwEx);
// 根据 Wrapper,查询一条记录
Map<String, Object> getMap(Wrapper<T> queryWrapper);
// 根据 Wrapper,查询一条记录
<V> V getObj(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);

list

// 查询所有
List<T> list();
// 查询列表
List<T> list(Wrapper<T> queryWrapper);
// 查询(根据ID 批量查询)
Collection<T> listByIds(Collection<? extends Serializable> idList);
// 查询(根据 columnMap 条件)
Collection<T> listByMap(Map<String, Object> columnMap);
// 查询所有列表
List<Map<String, Object>> listMaps();
// 查询列表
List<Map<String, Object>> listMaps(Wrapper<T> queryWrapper);
// 查询全部记录
List<Object> listObjs();
// 查询全部记录
<V> List<V> listObjs(Function<? super Object, V> mapper);
// 根据 Wrapper 条件,查询全部记录
List<Object> listObjs(Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询全部记录
<V> List<V> listObjs(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);

page

// 无条件分页查询
IPage<T> page(IPage<T> page);
// 条件分页查询
IPage<T> page(IPage<T> page, Wrapper<T> queryWrapper);
// 无条件分页查询
IPage<Map<String, Object>> pageMaps(IPage<T> page);
// 条件分页查询
IPage<Map<String, Object>> pageMaps(IPage<T> page, Wrapper<T> queryWrapper);

Mapper原生CURD接口

insert

int insert(T entity);

delete

    int deleteById(Serializable id);

    int deleteById(T entity);

    int deleteByMap(@Param("cm") Map<String, Object> columnMap);

    int delete(@Param("ew") Wrapper<T> queryWrapper);

    int deleteBatchIds(@Param("coll") Collection<? extends Serializable> idList);

update

    int updateById(@Param("et") T entity);

    int update(@Param("et") T entity, @Param("ew") Wrapper<T> updateWrapper);

select

    T selectById(Serializable id);

    List<T> selectBatchIds(@Param("coll") Collection<? extends Serializable> idList);

    List<T> selectByMap(@Param("cm") Map<String, Object> columnMap);

    default T selectOne(@Param("ew") Wrapper<T> queryWrapper) {
        List<T> ts = this.selectList(queryWrapper);
        if (CollectionUtils.isNotEmpty(ts)) {
            if (ts.size() != 1) {
                throw ExceptionUtils.mpe("One record is expected, but the query result is multiple records", new Object[0]);
            } else {
                return ts.get(0);
            }
        } else {
            return null;
        }
    }

    Long selectCount(@Param("ew") Wrapper<T> queryWrapper);

    List<T> selectList(@Param("ew") Wrapper<T> queryWrapper);

    List<Map<String, Object>> selectMaps(@Param("ew") Wrapper<T> queryWrapper);

    List<Object> selectObjs(@Param("ew") Wrapper<T> queryWrapper);

page

    <P extends IPage<T>> P selectPage(P page, @Param("ew") Wrapper<T> queryWrapper);

    <P extends IPage<Map<String, Object>>> P selectMapsPage(P page, @Param("ew") Wrapper<T> queryWrapper);

自动分页

原理

  1. 分页拦截器PaginationInnerInterceptor对所有查询请求进行拦截,beforeQuery查询时,首先判断参数中是否包含IPage类型参数。
  2. 若包含IPage类型参数,则根据传参值进行分页查询,否则,不分页。

PaginationInnerInterceptor源码

位置:mybatis-plus-extension-3.4.3.4.jar#PaginationInnerInterceptor

public class PaginationInnerInterceptor implements InnerInterceptor {
    public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
    	//判断并寻找IPage参数
        IPage<?> page = (IPage)ParameterUtils.findPage(parameter).orElse((Object)null);
        //参数中包含IPage类型参数,则执行分页
        if (null != page) {
            boolean addOrdered = false;
            String buildSql = boundSql.getSql();
            List<OrderItem> orders = page.orders();
            if (CollectionUtils.isNotEmpty(orders)) {
                addOrdered = true;
                buildSql = this.concatOrderBy(buildSql, orders);
            }
			//根据page参数,组装分页查询sql
            Long _limit = page.maxLimit() != null ? page.maxLimit() : this.maxLimit;
            //无需分页
            if (page.getSize() < 0L && null == _limit) {
                if (addOrdered) {
                    PluginUtils.mpBoundSql(boundSql).sql(buildSql);
                }

            } else {
                this.handlerLimit(page, _limit);
                IDialect dialect = this.findIDialect(executor);
                Configuration configuration = ms.getConfiguration();
                //构建分页sql
                DialectModel model = dialect.buildPaginationSql(buildSql, page.offset(), page.getSize());
                MPBoundSql mpBoundSql = PluginUtils.mpBoundSql(boundSql);
                List<ParameterMapping> mappings = mpBoundSql.parameterMappings();
                Map<String, Object> additionalParameter = mpBoundSql.additionalParameters();
                model.consumers(mappings, configuration, additionalParameter);
                mpBoundSql.sql(model.getDialectSql());
                mpBoundSql.parameterMappings(mappings);
            }
        }
    }
}

ParameterUtils

位置:mybatis-plus-core-3.4.3.4.jar#ParameterUtils

public class ParameterUtils {
    private ParameterUtils() {
    }

    public static Optional<IPage> findPage(Object parameterObject) {
        if (parameterObject != null) {
        	//若多个参数,转为map对象,任意一个value包含IPage类型对象,则返回IPage对象
            if (parameterObject instanceof Map) {
                Map<?, ?> parameterMap = (Map)parameterObject;
                Iterator var2 = parameterMap.entrySet().iterator();

                while(var2.hasNext()) {
                    Entry entry = (Entry)var2.next();
                    if (entry.getValue() != null && entry.getValue() instanceof IPage) {
                        return Optional.of((IPage)entry.getValue());
                    }
                }
            } else if (parameterObject instanceof IPage) {
            	//单个参数,若类型为IPage,则返回IPage对象
                return Optional.of((IPage)parameterObject);
            }
        }
		//参数中无IPage类型参数,则返回空
        return Optional.empty();
    }
}

public class MySqlDialect implements IDialect {
    public MySqlDialect() {
    }

    public DialectModel buildPaginationSql(String originalSql, long offset, long limit) {
    	//拼接构建分页sql
        StringBuilder sql = (new StringBuilder(originalSql)).append(" LIMIT ").append("?");
        if (offset != 0L) {
            sql.append(",").append("?");
            return (new DialectModel(sql.toString(), offset, limit)).setConsumerChain();
        } else {
            return (new DialectModel(sql.toString(), limit)).setConsumer(true);
        }
    }
}

lambda函数

Compare接口源码

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.baomidou.mybatisplus.core.conditions.interfaces;

import java.io.Serializable;
import java.util.Map;
import java.util.function.BiPredicate;

public interface Compare<Children, R> extends Serializable {
    default <V> Children allEq(Map<R, V> params) {
        return this.allEq(params, true);
    }

    default <V> Children allEq(Map<R, V> params, boolean null2IsNull) {
        return this.allEq(true, params, null2IsNull);
    }

    <V> Children allEq(boolean condition, Map<R, V> params, boolean null2IsNull);

    default <V> Children allEq(BiPredicate<R, V> filter, Map<R, V> params) {
        return this.allEq(filter, params, true);
    }

    default <V> Children allEq(BiPredicate<R, V> filter, Map<R, V> params, boolean null2IsNull) {
        return this.allEq(true, filter, params, null2IsNull);
    }

    <V> Children allEq(boolean condition, BiPredicate<R, V> filter, Map<R, V> params, boolean null2IsNull);

    default Children eq(R column, Object val) {
        return this.eq(true, column, val);
    }

    Children eq(boolean condition, R column, Object val);

    default Children ne(R column, Object val) {
        return this.ne(true, column, val);
    }

    Children ne(boolean condition, R column, Object val);

    default Children gt(R column, Object val) {
        return this.gt(true, column, val);
    }

    Children gt(boolean condition, R column, Object val);

    default Children ge(R column, Object val) {
        return this.ge(true, column, val);
    }

    Children ge(boolean condition, R column, Object val);

    default Children lt(R column, Object val) {
        return this.lt(true, column, val);
    }

    Children lt(boolean condition, R column, Object val);

    default Children le(R column, Object val) {
        return this.le(true, column, val);
    }

    Children le(boolean condition, R column, Object val);

    default Children between(R column, Object val1, Object val2) {
        return this.between(true, column, val1, val2);
    }

    Children between(boolean condition, R column, Object val1, Object val2);

    default Children notBetween(R column, Object val1, Object val2) {
        return this.notBetween(true, column, val1, val2);
    }

    Children notBetween(boolean condition, R column, Object val1, Object val2);

    default Children like(R column, Object val) {
        return this.like(true, column, val);
    }

    Children like(boolean condition, R column, Object val);

    default Children notLike(R column, Object val) {
        return this.notLike(true, column, val);
    }

    Children notLike(boolean condition, R column, Object val);

    default Children likeLeft(R column, Object val) {
        return this.likeLeft(true, column, val);
    }

    Children likeLeft(boolean condition, R column, Object val);

    default Children likeRight(R column, Object val) {
        return this.likeRight(true, column, val);
    }

    Children likeRight(boolean condition, R column, Object val);
}

Func接口源码

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.baomidou.mybatisplus.core.conditions.interfaces;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.function.Consumer;

public interface Func<Children, R> extends Serializable {
    default Children isNull(R column) {
        return this.isNull(true, column);
    }

    Children isNull(boolean condition, R column);

    default Children isNotNull(R column) {
        return this.isNotNull(true, column);
    }

    Children isNotNull(boolean condition, R column);

    default Children in(R column, Collection<?> coll) {
        return this.in(true, column, coll);
    }

    Children in(boolean condition, R column, Collection<?> coll);

    default Children in(R column, Object... values) {
        return this.in(true, column, values);
    }

    Children in(boolean condition, R column, Object... values);

    default Children notIn(R column, Collection<?> coll) {
        return this.notIn(true, column, coll);
    }

    Children notIn(boolean condition, R column, Collection<?> coll);

    default Children notIn(R column, Object... value) {
        return this.notIn(true, column, value);
    }

    Children notIn(boolean condition, R column, Object... values);

    default Children inSql(R column, String inValue) {
        return this.inSql(true, column, inValue);
    }

    Children inSql(boolean condition, R column, String inValue);

    Children gtSql(boolean condition, R column, String inValue);

    default Children gtSql(R column, String inValue) {
        return this.gtSql(true, column, inValue);
    }

    Children geSql(boolean condition, R column, String inValue);

    default Children geSql(R column, String inValue) {
        return this.geSql(true, column, inValue);
    }

    Children ltSql(boolean condition, R column, String inValue);

    default Children ltSql(R column, String inValue) {
        return this.ltSql(true, column, inValue);
    }

    Children leSql(boolean condition, R column, String inValue);

    default Children leSql(R column, String inValue) {
        return this.leSql(true, column, inValue);
    }

    default Children notInSql(R column, String inValue) {
        return this.notInSql(true, column, inValue);
    }

    Children notInSql(boolean condition, R column, String inValue);

    Children groupBy(boolean condition, R column);

    default Children groupBy(R column) {
        return this.groupBy(true, column);
    }

    Children groupBy(boolean condition, List<R> columns);

    default Children groupBy(List<R> columns) {
        return this.groupBy(true, columns);
    }

    /** @deprecated */
    @Deprecated
    default Children groupBy(R column, R... columns) {
        return this.groupBy(true, column, columns);
    }

    /** @deprecated */
    @Deprecated
    Children groupBy(boolean condition, R column, R... columns);

    default Children orderByAsc(boolean condition, R column) {
        return this.orderBy(condition, true, column);
    }

    default Children orderByAsc(R column) {
        return this.orderByAsc(true, column);
    }

    default Children orderByAsc(boolean condition, List<R> columns) {
        return this.orderBy(condition, true, columns);
    }

    default Children orderByAsc(List<R> columns) {
        return this.orderByAsc(true, columns);
    }

    /** @deprecated */
    @Deprecated
    default Children orderByAsc(R column, R... columns) {
        return this.orderByAsc(true, column, columns);
    }

    /** @deprecated */
    @Deprecated
    default Children orderByAsc(boolean condition, R column, R... columns) {
        return this.orderBy(condition, true, column, columns);
    }

    default Children orderByDesc(boolean condition, R column) {
        return this.orderBy(condition, false, column);
    }

    default Children orderByDesc(R column) {
        return this.orderByDesc(true, column);
    }

    default Children orderByDesc(boolean condition, List<R> columns) {
        return this.orderBy(condition, false, columns);
    }

    default Children orderByDesc(List<R> columns) {
        return this.orderByDesc(true, columns);
    }

    /** @deprecated */
    @Deprecated
    default Children orderByDesc(R column, R... columns) {
        return this.orderByDesc(true, column, columns);
    }

    /** @deprecated */
    @Deprecated
    default Children orderByDesc(boolean condition, R column, R... columns) {
        return this.orderBy(condition, false, column, columns);
    }

    Children orderBy(boolean condition, boolean isAsc, R column);

    Children orderBy(boolean condition, boolean isAsc, List<R> columns);

    /** @deprecated */
    @Deprecated
    Children orderBy(boolean condition, boolean isAsc, R column, R... columns);

    default Children having(String sqlHaving, Object... params) {
        return this.having(true, sqlHaving, params);
    }

    Children having(boolean condition, String sqlHaving, Object... params);

    default Children func(Consumer<Children> consumer) {
        return this.func(true, consumer);
    }

    Children func(boolean condition, Consumer<Children> consumer);
}

Join接口源码

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.baomidou.mybatisplus.core.conditions.interfaces;

import java.io.Serializable;

public interface Join<Children> extends Serializable {
    default Children or() {
        return this.or(true);
    }

    Children or(boolean condition);

    default Children apply(String applySql, Object... values) {
        return this.apply(true, applySql, values);
    }

    Children apply(boolean condition, String applySql, Object... values);

    default Children last(String lastSql) {
        return this.last(true, lastSql);
    }

    Children last(boolean condition, String lastSql);

    default Children comment(String comment) {
        return this.comment(true, comment);
    }

    Children comment(boolean condition, String comment);

    default Children first(String firstSql) {
        return this.first(true, firstSql);
    }

    Children first(boolean condition, String firstSql);

    default Children exists(String existsSql, Object... values) {
        return this.exists(true, existsSql, values);
    }

    Children exists(boolean condition, String existsSql, Object... values);

    default Children notExists(String existsSql, Object... values) {
        return this.notExists(true, existsSql, values);
    }

    Children notExists(boolean condition, String existsSql, Object... values);
}

Nested接口源码

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.baomidou.mybatisplus.core.conditions.interfaces;

import java.io.Serializable;
import java.util.function.Consumer;

public interface Nested<Param, Children> extends Serializable {
    default Children and(Consumer<Param> consumer) {
        return this.and(true, consumer);
    }

    Children and(boolean condition, Consumer<Param> consumer);

    default Children or(Consumer<Param> consumer) {
        return this.or(true, consumer);
    }

    Children or(boolean condition, Consumer<Param> consumer);

    default Children nested(Consumer<Param> consumer) {
        return this.nested(true, consumer);
    }

    Children nested(boolean condition, Consumer<Param> consumer);

    default Children not(Consumer<Param> consumer) {
        return this.not(true, consumer);
    }

    Children not(boolean condition, Consumer<Param> consumer);
}

常用函数总结

函数名说明示例与对应sql
eq等于=eq(“id”, 1)

id = 1
ne不等于<>ne(“id”, 1)

id <> 1
gt大于>gt(“id”, 1)

id > 1
ge大于等于>=ge(“id”,1) 即 id >= 1
lt小于<lt(“id”,1)

id < 1
le小于等于<=le("id,1)

id <= 1
betweenBETWEEN 值1 AND 值2between(“id”, 1, 3)

id BETWEEN 1 AND 3
notBetweenNOT BETWEEN 值1 AND 值2notBetween(“id”, 1, 3)

id NOT BETWEEN 1 AND 3
likeLIKE ‘%值%’like(“name”, "小”)

name LIKE ‘%小%’
notLikeNOT LIKE ‘%值%’notLike(“name”, "小”)

name NOT LIKE ‘%小%’
likeLeftLIKE ‘%值’likeLeft(“name”, "小”)

name LIKE ‘%小’
likeRightLIKE ‘值%’likeRight(“name”, "小”)

name LIKE ‘小%’
isNull字段 IS NULLisNull(“name”)

name IS NULL
isNotNull字段 IS NOT NULLisNotNull(“name”)

name IS NOT NULL
in字段 IN (值1, 值2, … …)in(“id”, {1,2,3,4,5})

id IN (1,2,3,4,5)
notIn字段 NOT IN (值1, 值2, … …)notIn(“id”, {1,2,3,4,5})

id NOT IN (1,2,3,4,5)
inSql字段 IN (sql语句)inSql(“id”, “select id from tab_01 where id > 10”)

id IN (select id from tab_01 where id > 10)
notInSql字段 NOT IN (sql语句)notInSql(“id”, “select id from tab_01 where id > 10”)

id NOT IN (select id from tab_01 where id > 10)
groupByGROUP BY 字段1, 字段2, … …groupBy(“id”, “name”)

GROUP BY id, name
orderByORDER BY 字段1, 字段2, … …orderBy(true, false, “id”, “name”)

ORDER BY id ASC, name DESC
orderByAscORDER BY 字段1, 字段2, … … ASCorderByAsc(“id”, “name”)

ORDER BY id ASC, name ASC
orderByDescORDER BY 字段1, 字段2, … … DESCorderByDesc(“id”, “name”)

ORDER BY id DESC, name DESC
havingHAVING(sql语句)having(“count(number) > {0}”, 20)

HAVING COUNT(number) > 20
orOReq(“id”, 2).or().eq(“name”, “小红”)

id = 2 OR name = “小红”
andANDand(query -> query.eq(“id”, 2).ne(“name”, "小红”))

AND (id = 2 AND name <> “小红”
apply拼接sql语句apply("date_format(df, ‘%Y-%m-%d’) = {0}, “2023-04-25”)

date_format(df, ‘%Y-%m-%d’) = ‘2023-04-25’)
last拼接sql到最后last(“limit”, 10)

xxx limit 10
existsEXISTS (sql语句)exists("select id from tab_01 where name = “小红”)

EXISTS ("select id from tab_01 where name = “小红”)
notExistsNOT EXISTS (sql语句)notExists("select id from tab_01 where name = “小红”)

NOT EXISTS ("select id from tab_01 where name = “小红”)
nested不带AND或OR的嵌套nested(query -> query.eq(“id”, 2).ne(“name”, "小红”))

(id = 2 AND name <> “小红”

MyBatis-Plus 代码实践

依赖

<dependency>
      <groupId>com.baomidou</groupId>
      <artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>

分页插件配置

@Configuration
public class MybatisPlusConfig {
    /**
     * mybatis-plus 拦截器
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        //新增内置分页拦截器,并设置数据库类型为mysql
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}

IDEA插件MyBatisPlus

  1. 【preferences】—>【Plugins】—>【Marketplace】
  2. 搜索并安装MyBatisPlus插件,可以通过该插件进行Mapper层与xml之间的映射跳转。
    在这里插入图片描述

类模板

entity类

@Data
@TableName("demo_entity")
@ApiModel(value = "demo表")
public class DemoEntity {

    /**
     * id
     */
    @TableId(type = IdType.ASSIGN_ID)
    private Long id;

    /**
     * 名称
     */
    private String name;

    /**
     * 编码
     */
    private String code;
	
	/**
     * 是否删除
     */
    private Integer deleted;
}

mapper类

@Mapper
public interface DemoEntityMapper extends BaseMapper<DemoEntity> {
... ...
}

service接口类

public interface DemoEntityService extends IService<DemoEntity> {
... ...
}

service实现类

@Slf4j
@Service
public class DemoEntityServiceImpl extends ServiceImpl<DemoEntityMapper, DemoEntity> implements DemoEntityService{
	/**
 	* mapper
 	*/
	@Autowired
	private DemoEntityMapper demoEntityMapper;
	
	... ...
}

lambda表达式

LambdaQueryWrapper查询

... ...
Long id = 1000L;
List<Long> userId = new ArrayList<>();
userId.add(100000L);
userId.add(100001L);
LambdaQueryWrapper<DemoEntity> lambdaQueryWrapper = new LambdaQueryWrapper();
lambdaQueryWrapper.eq(DemoEntity::getId, id)
                    .in(DemoEntity::getUserId, userId);
List<DemoEntity> entityList = demoEntityMapper.selectList(lambdaQueryWrapper);
... ...

QueryWrapper查询

... ...
Long id = 1000L;
List<Long> userId = new ArrayList<>();
userId.add(100000L);
userId.add(100001L);
QueryWrapper<DemoEntity> queryWrapper = Wrappers.query();
queryWrapper.lambda()
	//and筛选  
	.and(wrapper -> wrapper.in(DemoEntity::getUserId, userId)
	//or条件
	.or()
	.eq(DemoEntity::getId, id);
... ...

lambdaUpdate更新

... ...
Long id = 1000L;
this.lambdaUpdate()
    .eq(DemoEntity::getId, id)
    .set(DemoEntity::getUserId, 10000002L)
    //更新
    .update();
... ...

Mapper结合xml文件查询

根据基本数据类型查询

mapper方法

@Mapper
public interface DemoEntityMapper extends BaseMapper<DemoEntity> {
... ...
	/**
 	* 根据id进行查询
 	* @param id
 	* @return
 	*/
	public DemoVO getById(int id);
... ...
}

DemoEntityMapper.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.ljy.demo.mapper.DemoEntityMapper">
	<select id="getById" parameterType="int" resultType="com.ljy.demo.vo.DemoVO">
        SELECT * FROM demo_entity WHERE id=#{id}
    </select>
</mapper>

根据多个参数查询

mapper方法

@Mapper
public interface DemoEntityMapper extends BaseMapper<DemoEntity> {
... ...
	/**
 	* 根据name和code进行查询
 	* @param name
 	* @param code
 	* @return
 	*/
	public List<DemoVO> getByNameOrCode(String name, String code);
... ...
}

DemoEntityMapper.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.ljy.demo.mapper.DemoEntityMapper">
	<select id="getByNameOrCode" resultType="com.ljy.demo.vo.DemoVO">
        SELECT * FROM demo_entity WHERE name=#{0} OR code=#{1}
    </select>
</mapper>

根据对象参数查询

mapper方法

@Mapper
public interface DemoEntityMapper extends BaseMapper<DemoEntity> {
... ...
	/**
 	* 根据dto的不同入参进行查询
 	* @param demoDTO
 	* @return
 	*/
	public List<DemoVO> listDemo(@Param("dto") DemoDTO demoDTO);
... ...
}

DemoEntityMapper.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.ljy.demo.mapper.DemoEntityMapper">

    <sql id="List_demo">
        select de.id,
               de.name,
               de.code
        from demo_entity de
    </sql>

    <select id="listDemo" resultType="com.ljy.demo.vo.DemoVO">
        <include refid="List_demo"/>

        <where>
            <if test="dto.id != null" >
            	 <!--id不为空,则精准查询-->
                and de.id = #{dto.id}
            </if>
            <if test="dto.name != null and dto.name != ''">
                <!--名称不为空,则模糊查询-->
                and de.name like concat('%',#{dto.name},'%')
            </if>
            <!--未删除-->
            and de.deleted = 0
        </where>
        group by de.id
        order by de.name desc
    </select>
</mapper>

分页查询

mapper方法

@Mapper
public interface DemoEntityMapper extends BaseMapper<DemoEntity> {
... ...
	/**
 	* 分页查询
 	* @param page
 	* @param demoDTO
 	* @return
 	*/
	IPage<DemoVO> pageListDemo(@Param("page") IPage<DemoVO> page, @Param("dto") DemoDTO demoDTO);
... ...
}

DemoEntityMapper.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.ljy.demo.mapper.DemoEntityMapper">

    <sql id="List_demo">
        select de.id,
               de.name,
               de.code
        from demo_entity de
    </sql>
	<!--名称保持一致-->
    <select id="pageListDemo" resultType="com.ljy.demo.vo.DemoVO">
        <include refid="List_demo"/>
        <where>
            <if test="dto.name != null and dto.name != ''">
                <!--名称不为空,则模糊查询-->
                and de.name like concat('%',#{dto.name},'%')
            </if>
            <!--未删除-->
            and de.deleted = 0
        </where>
        group by de.id
        order by de.name desc
    </select>
</mapper>

调用代码

...
//构造分页
Page<DemoVO> page = new Page<>(2, 10);
//page 查询
IPage<DemoVO> iPage = demoEntityMapper.pageListDemo(page, demoDTO);
...

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

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

相关文章

抚仙湖,一个亦梦亦幻的地方,这个五一节,我们骑友′的诗和远方

云南省玉溪市抚仙湖是中国南方最大的深水型淡水湖泊之一&#xff0c;位于云南省中部&#xff0c;距离昆明市约80公里。抚仙湖的面积约为212平方公里&#xff0c;平均水深约为120米&#xff0c;最大水深可达157米。 抚仙湖最美的景点有很多&#xff0c;其中最著名的是以下几个&a…

2023年五月份图形化二级打卡试题

活动时间 从2023年5月1日至5月21日&#xff0c;每天一道编程题。 本次打卡的规则如下&#xff1a; 小朋友每天利用10~15分钟做一道编程题&#xff0c;遇到问题就来群内讨论&#xff0c;我来给大家答疑。 小朋友做完题目后&#xff0c;截图到朋友圈打卡并把打卡的截图发到活动群…

深度学习技巧应用9-模型训练中学习率的调整和假数据生成技巧与总结

大家好,我是微学AI,今天给大家介绍一下深度学习技巧应用9-模型训练中学习率的调整和假数据生成技巧与总结,我们在训练模型的时候,为了测试模型是否可以行,但是目前还没有标注好大量的数据,在缺乏数据的情况下,今天教大家如何生成假数据(测试数据)进行模型调试,并且教…

时间序列预测(一)基于Prophet的销售额预测

时间序列预测&#xff08;一&#xff09;基于Prophet的销售额预测 小O&#xff1a;小H&#xff0c;有没有什么方法能快速的预测下未来的销售额啊 小H&#xff1a;Facebook曾经开源了一款时间序列预测算法fbprophet&#xff0c;简单又快速&#xff5e; 传统的时间序列算法很多&a…

mac电脑怎么录屏?2招轻松搞定!

案例&#xff1a;怎样对mac电脑进行屏幕录制&#xff1f; 【之前一直使用的是Windows电脑&#xff0c;对Windows电脑比较熟悉。最近换了一台苹果电脑&#xff0c;不知道使用它怎么进行电脑录屏。求一个好用的苹果电脑录屏方法&#xff01;】 在我们的日常工作和生活中&#x…

c++ 对类与对象的基础框架+完整思维导图+基本练习题+深入细节+通俗易懂建议收藏

绪论 上一章&#xff0c;我们将c入门的基础知识进行了学习&#xff0c;本章其实才算真正的跨入到c开始可能比较难&#xff0c;但只有我们唯有不断的前进&#xff0c;才能斩断荆棘越过人生的坎坷&#xff01; 话不多说安全带系好&#xff0c;发车啦&#xff08;建议电脑观看&…

【原创】用Matplotlib绘制的图表,真的是太惊艳了!!

当我们谈论Python中的数据可视化&#xff0c;Matplotlib是一个不可或缺的库。它强大的功能和灵活性使我们能够以各种方式轻松地呈现数据。然而&#xff0c;有时候&#xff0c;我们可能会忽视Matplotlib在创建视觉上令人惊叹的图像方面的潜力。在本文中&#xff0c;我们将探讨如…

C语言数据结构+KMP算法next数组优化计算方法+优化后子串匹配代码实现

KMP算法next数组优化版 一.计算根据下列模式串计算出next数组二.优化next数组三.用优化后next的数组代码实现子串的匹配总结 通过我之前那篇KMP算法的讲解,我们可以快速手算KMP算法的next数组,但是之前计算的next数组在一些情况下会有缺陷,比如模式串’aaaab’和主串’aaabaaaa…

人人都能用,3s学会加密你的网址变成ooo

文章目录 1 前言2 原理及使用方法3 这玩意有什么用3.1 简单加密网址3.2 隐藏二级目录3.3 彩蛋&#xff1a;无限月读3.4 探讨性的加密应用 4 转换的代码4.1 将字符转为utf8数组4.2 将utf8数组转换为字符串4.3 最终转换4.4 用R来实现 5 讨论 1 前言 大家可以复制一下这个网址到浏…

[JavaEE初阶] 类加载机制

在真正的战争到来之前,尽可能地变得强大吧~ 文章目录 前言1. 类加载1.1 类加载的过程1.2 类加载的时机1.3 双亲委派模型 前言 这个问题是面试经典题,让我们来求甚解吧~ 1. 类加载 1.1 类加载的过程 如下图 加载,找到.class文件,读取文件内容验证,验证.class文件的格式是否…

IntelliJ IDEA 接入ChatGPT (免费,无需注册)生产力被干爆了!

IntelliJ IDEA 接入ChatGPT 前言 : 今天给大家介绍一款好用的 IntelliJ IDEA ChatGPT 插件 可以帮助我们写代码&#xff0c;以及语言上的处理工作&#xff0c;以及解释代码。让我们的生产力大大提高&#xff01; 一. ChatGPT-Plus 功能介绍 支持最新idea版本AI询问功能,写好…

记录一次adb+frida+hook学习经过

adb连接模拟器 adb devices 查看adb 连接设备 offline 表示设备未连接成功或无响应&#xff0c;device 设备已连接 未连接就使用adb connect 127.0.0.1:端口号 各种模拟器端口号及模拟器连接方式_雷电模拟器 调式串口_宋学慧的博客-CSDN博客 举个栗子 常见adb命令 adb vers…

NXP公司LPC21XX+PID实现稳定温度控制

本例使用的是LPC21XX系列芯片提供的PWM功能实现稳定的温度控制。首先我们获得当前环境温度之后&#xff0c;再用设定的温度与当前温度相减&#xff0c;通过PID算法计算出当前输出脉宽&#xff0c;并将其输出到L298N模块中&#xff0c;使加热丝发热&#xff0c;形成闭环&#xf…

Java核心技术 卷1-总结-18

Java核心技术 卷1-总结-18 同步Volatile域final变量原子性死锁线程局部变量锁测试与超时读/写锁 同步 Volatile域 多处理器的计算机能够暂时在寄存器或本地内存缓冲区中保存内存中的值。结果是&#xff0c;运行在不同处理器上的线程可能在同一个内存位置取到不同的值。编译器…

建仓价和持仓价的应用:如何开仓如何持仓

建仓、持仓&#xff0c;是交易中绕不开的话题&#xff0c;没有建仓、持仓&#xff0c;何来建仓价、持仓价呢&#xff1f;所以这也是基础问题。不过作为市场形式的表现来说&#xff0c;建仓、持仓到后来的平仓贯彻始终&#xff0c;虽然是基础问题&#xff0c;也是后面登堂入室、…

【图数据库实践教程】Ubuntu22.04-Neo4j中文版安装及导入owl文件(通用教程)

文章目录 0. 环境准备0.1 静态配置IP&#xff1a;192.168.1.54&#xff0c;及网卡类型&#xff1a;NAT模式0.2 激活root用户&#xff1a;0.3 更改apt国内镜像源&#xff08;下载快&#xff09;0.4 关闭相关防火墙等保证网络顺畅 1. 相关软件安装1.1 安装好服务器内的相关软件1.…

FL Studio2023中文版数字音频工作站(DAW)软件

FL Studio21水果软件能支持制作各种音乐类型&#xff0c;除了最擅长的电子音乐&#xff0c;还可以任意创作流行音乐、古典音乐、民族音乐、乡村音乐、爵士乐等等&#xff0c;没有音乐类型的限制&#xff0c;让你的音乐突破想象力的限制。 FL Studio 2023中文版是数字音频工作站…

LINUX的系统管理与维护命令

文章目录 一、LINUX的系统管理与维护命令总结 一、LINUX的系统管理与维护命令 - Linux ls命令:显示指定工作目录下的内容 Linux pwd命令:显示当前工作目录 Linux cd命令:切换工作目录 Linux date命令:显示或设置系统时间 Linux su命令:切换用户 Linux clear命令:清除屏幕 Li…

5种简单快速的方法解除PDF文件密码保护

PDF 文件已经成为了我们日常工作、学习中广泛使用的文档格式之一。为了对重要的 PDF 文件进行保护&#xff0c;我们有时需要添加密码保护功能来防止未授权访问或修改。但是&#xff0c;如果您的 PDF 文件已经有了密码保护&#xff0c;而您需要快速访问和编辑它们&#xff0c;那…

机器人工程师与孔乙己文学

本文内容严格按创作模板发布&#xff1a; 孔乙已是鲁迅笔下人物&#xff0c;穷困流倒还穿着象征读书人的长衫&#xff0c;迁腐、麻木。最近&#xff0c;大家自我调佩是“当代孔乙己”&#xff0c;学历成为思想负担&#xff0c;找工作时高不成低不就。你可以从以下几个角度说说…