springboot3 集成mybatis 和通用mapper

xml版本查看:https://www.cnblogs.com/binz/p/6564490.html

springboot3.x以前的版本查看 https://www.cnblogs.com/binz/p/17421063.html

springboot3.x查看  https://www.cnblogs.com/binz/p/17654403.html

1、pom引用

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.1.2</version>
 </parent>

<dependencies>
     <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                    <groupId>org.springframework.boot</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        
        <!-- web 容器使用 undertow 性能更强 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-undertow</artifactId>
        </dependency>

        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.4.7</version>
        </dependency>
<!-- 以前的tkmapper 不支持springboot3.x -->
<!-- 具体查看https://mapper.mybatis.io/--> <dependency> <groupId>io.mybatis</groupId> <artifactId>mybatis-mapper</artifactId> <version>2.1.1</version> </dependency>
<dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>3.0.2</version> </dependency>


    <!-- openapi、 swagger3、knife4j配置,适用boot3 -->
    <!-- https://doc.xiaominfo.com -->
    <dependency>
      <groupId>com.github.xiaoymin</groupId>
      <artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
      <version>4.3.0</version>
    </dependency>
    <!-- openapi配置 -->

    
</dependencies>    

2、新建自己的BaseMapper

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import org.apache.ibatis.session.RowBounds;

import com.github.pagehelper.Page;
import cn.hutool.core.bean.BeanUtil;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import io.mybatis.mapper.Mapper;
import io.mybatis.mapper.example.Example;
import io.mybatis.mapper.example.LambdaExampleWrapper;

public interface BaseMapper<T> extends Mapper<T,Long>{
    
    List<T> selectList(T entity, RowBounds rowBounds);

    default T getById(Long id) {
        return selectByPrimaryKey(id).orElse(null);
    }

    default <RE extends Serializable> RE getById(Long id,Class<RE> returnClass) {
        T t = getById(id);
        if(t != null) {
            return covert(t,returnClass);
        }
        return null;
    }

    default T one(T query) {
        return selectOne(query).orElse(null);
    }


    default <RE extends Serializable> RE one(T query,Class<RE> returnClass) {
        Optional<T> optional = selectOne(query);
        if(optional.isPresent()) {
            T t = optional.get();
            return covert(t,returnClass);
        }
        return null;
    }


    default <RE extends Serializable> List<RE> select(T t,Class<RE> returnClass) {
        List<T> ts = selectList(t);
        return covertList(ts,returnClass);
    }

    default <RE extends Serializable> Page<RE> selectPage(T t,Class<RE> returnClass) {
        Page<T> ts = (Page<T>) selectList(t);
        return (Page<RE>) covertList(ts,returnClass);
    }

    default <RE extends Serializable> Page<RE> selectPageByExample(Example<T> example,Class<RE> returnClass) {
        Page<T> ts = (Page<T>) selectByExample(example);
        return (Page<RE>) covertList(ts,returnClass);
    }



    default <RE extends Serializable> List<RE> selectByExample(Example<T> example,Class<RE> returnClass) {
        List<T> ts = selectByExample(example);
        return covertList(ts,returnClass);
    }

    default <RE extends Serializable> RE selectOneByExample(Example<T> example,Class<RE> returnClass) {
        Optional<T> optional = selectOneByExample(example);
        if(optional.isPresent()) {
            T t = optional.get();
            return covert(t,returnClass);
        }
        return null;
    }

    default <RE extends Serializable> RE selectOneByExampleLimitOne(Example<T> example,Class<RE> returnClass) {
        T t = selectOneByExampleLimitOne(example);
        if(t != null) {
            return covert(t, returnClass);
        }
        return null;
    }

    default T selectOneByExampleLimitOne(Example<T> example) {
        RowBounds rowBounds = new RowBounds(0, 1);
        List<T> ts = selectByExample(example, rowBounds);
        if(ObjectUtil.isNotEmpty(ts)) {
            return ts.get(0);
        }
        return null;
    }



    default T selectOneByLimitOne(T t) {
        RowBounds rowBounds = new RowBounds(0, 1);
        List<T> ts = selectList(t,rowBounds);
        if(ObjectUtil.isNotEmpty(ts)) {
            return ts.get(0);
        }
        return null;
    }


    @SuppressWarnings("unchecked")
    default Class<T> thisTClass() {
        Class<?> class1 = getClass();
        Class<?> interfaces = class1.getInterfaces()[0];
        Type[] genericInterfaces = interfaces.getGenericInterfaces();
        Type type = genericInterfaces[0];
        if( type instanceof ParameterizedType){
            ParameterizedType pType = (ParameterizedType) type;
            Type clazz = pType.getActualTypeArguments()[0];
            if( clazz instanceof Class<?> ){
                return (Class<T>) clazz;
            }
        }
        return null;
    }

    default <RE extends Serializable> List<RE> covertList(List<T> ts,Class<RE> returnClass){
        List<RE> responses;
        if(ts instanceof Page) {
            responses = new Page<>();
        }else {
            responses = new ArrayList<>();
        }
        for (T t : ts) {
            responses.add(covert(t,returnClass));
        }
        return responses;
    }

    default <RE extends Serializable> RE covert(T t , Class<RE> returnClass) {
        if(t != null) {
            RE response = null;
            try {
                response = ReflectUtil.newInstanceIfPossible(returnClass);
                BeanUtil.copy(t, response);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return response;
        }
        return null;
    }

    //自带的wrapper()个人觉得还缺点东西,就自己复制了一份出来微调了,根据情况使用,不需要就删除,需要对应的代码在下方
    default LambdaExampleWrapper<T> lambdaWrapper() {
        return new LambdaExampleWrapper<>(BaseMapper.this, example());
    }

}
View Code

3、新建表模型,注意注解使用和以前版本有区别,但是兼容一些之前javax.persistence的一些基本注解

import java.util.Date;

import io.mybatis.provider.Entity;
import lombok.Data;

@Data
@Entity.Table("system_user")
public class User {

    @Entity.Column(id = true,insertable = false,updatable = false)
    private Long id;

    /**
    * 姓名
    */
    private String realname;

    /**
    * 手机号
    */
    private String mobile;

    /**
    * 密码
    */
    private String password;

    /**
    * 身份证号
    */
    private String idcard;
    

    /**
    * 头像
    */
    private String avatar;

    /**
    * 最后登录时间
    */
    private String lastLoginIp;

    /**
    * 最后登录时间
    */
    private Date lastLoginTime;

    /**
    * 创建人
    */
    private Long createBy;

    /**
    * 创建时间
    */
    private Date createTime;

    /**
    * 修改人
    */
    private Long updateBy;

    /**
    * update_time
    */
    private Date updateTime;


}
View Code

4、创建对应业务的mapper继承BaseMapper

import com.xxx.core.base.BaseMapper;
import com.xxx.system.model.User;

public interface UserMapper extends BaseMapper<User>{


}

5、启动类扫描自己的mapper目录 @MapperScan

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.scheduling.annotation.EnableScheduling;

@EnableCaching
@EnableScheduling
@SpringBootApplication
@MapperScan(basePackages="com.xxx.*.mapper")
@ComponentScan(basePackages = { "com.xxx.*.config", "com.xxx.*.controller", "com.xxx.*.job" })
public class OperateApiStarted {
    public static void main(String[] args) {
        SpringApplication.run(OperateApiStarted.class, args);
    }
}

 6、创建io.mybatis.mapper.example.LambdaExampleWrapper

package io.mybatis.mapper.example;

import java.io.Serializable;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.apache.ibatis.exceptions.TooManyResultsException;
import org.apache.ibatis.session.RowBounds;

import com.github.pagehelper.Page;
import com.xxx.BaseMapper;
import com.xxx.BeanUtil;

import io.mybatis.common.util.Assert;
import io.mybatis.mapper.fn.Fn;

public class LambdaExampleWrapper<T> {


    private final BaseMapper<T>    baseMapper;
    private final Example<T>          example;
    private       Example.Criteria<T> current;

    public LambdaExampleWrapper(BaseMapper<T> baseMapper, Example<T> example) {
        this.baseMapper = baseMapper;
        this.example = example;
        this.current = example.createCriteria();
    }

    /**
     * or 一组条件
     *
     * @return 条件
     */
    public LambdaExampleWrapper<T> or() {
        this.current = this.example.or();
        return this;
    }

    /**
     * 获取查询条件
     */
    public Example<T> example() {
        return example;
    }

    /**
     * 清除条件,可重用
     */
    public LambdaExampleWrapper<T> clear() {
        this.example.clear();
        this.current = example.createCriteria();
        return this;
    }

    /**
     * 指定查询列
     *
     * @param fns 方法引用
     */
    @SafeVarargs
    public final LambdaExampleWrapper<T> select(Fn<T, Object>... fns) {
        this.example.selectColumns(fns);
        return this;
    }

    /**
     * 排除指定查询列
     *
     * @param fns 方法引用
     */
    @SafeVarargs
    public final LambdaExampleWrapper<T> exclude(Fn<T, Object>... fns) {
        this.example.excludeColumns(fns);
        return this;
    }

    /**
     * 设置起始 SQL
     *
     * @param startSql 起始 SQL,添加到 SQL 前,注意防止 SQL 注入
     */
    public LambdaExampleWrapper<T> startSql(String startSql) {
        this.example.setStartSql(startSql);
        return this;
    }

    /**
     * 设置结尾 SQL
     *
     * @param endSql 结尾 SQL,添加到 SQL 最后,注意防止 SQL 注入
     */
    public LambdaExampleWrapper<T> endSql(String endSql) {
        this.example.setEndSql(endSql);
        return this;
    }

    /**
     * 通过方法引用方式设置排序字段
     *
     * @param fn    排序列的方法引用
     * @param order 排序方式
     * @return Example
     */
    public LambdaExampleWrapper<T> orderBy(Fn<T, Object> fn, Example.Order order) {
        this.example.orderBy(fn, order);
        return this;
    }

    /**
     * 支持使用字符串形式来设置 order by,用以支持一些特殊的排序方案
     *
     * @param orderByCondition 排序字符串(不会覆盖已有的排序内容)
     * @return Example
     */
    public LambdaExampleWrapper<T> orderBy(String orderByCondition) {
        this.example.orderBy(orderByCondition);
        return this;
    }

    /**
     * 支持使用字符串形式来设置 order by,用以支持一些特殊的排序方案
     *
     * @param orderByCondition 排序字符串构造方法,比如通过数组集合循环拼接等
     * @return Example
     */
    public LambdaExampleWrapper<T> orderBy(Supplier<String> orderByCondition) {
        this.example.orderBy(orderByCondition);
        return this;
    }

    /**
     * 支持使用字符串形式来设置 order by,用以支持一些特殊的排序方案
     *
     * @param useOrderBy       条件表达式,true使用,false不使用 字符串排序
     * @param orderByCondition 排序字符串构造方法,比如通过数组集合循环拼接等
     * @return Example
     */
    public LambdaExampleWrapper<T> orderBy(boolean useOrderBy, Supplier<String> orderByCondition) {
        return useOrderBy ? this.orderBy(orderByCondition) : this;
    }

    /**
     * 通过方法引用方式设置排序字段,升序排序
     *
     * @param fns 排序列的方法引用
     * @return Example
     */
    @SafeVarargs
    public final LambdaExampleWrapper<T> orderByAsc(Fn<T, Object>... fns) {
        this.example.orderByAsc(fns);
        return this;
    }

    /**
     * 通过方法引用方式设置排序字段,降序排序
     *
     * @param fns 排序列的方法引用
     * @return Example
     */
    @SafeVarargs
    public final LambdaExampleWrapper<T> orderByDesc(Fn<T, Object>... fns) {
        this.example.orderByDesc(fns);
        return this;
    }

    /**
     * 设置 distince
     */
    public LambdaExampleWrapper<T> distinct() {
        this.example.setDistinct(true);
        return this;
    }

    /**
     * 设置更新字段和值
     *
     * @param useSet 表达式条件, true 使用,false 不使用
     * @param setSql "column = value"
     */
    public LambdaExampleWrapper<T> set(boolean useSet, String setSql) {
        return useSet ? set(setSql) : this;
    }

    /**
     * 设置更新字段和值
     *
     * @param setSql "column = value"
     */
    public LambdaExampleWrapper<T> set(String setSql) {
        this.example.set(setSql);
        return this;
    }

    /**
     * 设置更新字段和值
     *
     * @param useSet 表达式条件, true 使用,false 不使用
     * @param fn     字段
     * @param value  值
     */
    public LambdaExampleWrapper<T> set(boolean useSet, Fn<T, Object> fn, Object value) {
        return useSet ? set(fn, value) : this;
    }


    /**
     * 设置更新字段和值
     *
     * @param useSet   表达式条件, true 使用,false 不使用
     * @param fn       字段
     * @param supplier 值构造函数
     */
    public LambdaExampleWrapper<T> set(boolean useSet, Fn<T, Object> fn, Supplier<Object> supplier) {
        return useSet ? set(fn, supplier.get()) : this;
    }


    /**
     * 设置更新字段和值
     *
     * @param fn    字段
     * @param value 值
     */
    public LambdaExampleWrapper<T> set(Fn<T, Object> fn, Object value) {
        this.example.set(fn, value);
        return this;
    }

    /**
     * 指定字段为 null
     *
     * @param useCondition 表达式条件, true 使用,false 不使用
     * @param fn           字段对应的 get 方法引用
     */
    public LambdaExampleWrapper<T> isNull(boolean useCondition, Fn<T, Object> fn) {
        return useCondition ? isNull(fn) : this;
    }

    /**
     * 指定字段为 null
     *
     * @param fn 字段对应的 get 方法引用
     */
    public LambdaExampleWrapper<T> isNull(Fn<T, Object> fn) {
        this.current.addCriterion(fn.toColumn() + " IS NULL");
        return this;
    }

    /**
     * 指定字段不为 null
     *
     * @param useCondition 表达式条件, true 使用,false 不使用
     * @param fn           字段对应的 get 方法引用
     */
    public LambdaExampleWrapper<T> isNotNull(boolean useCondition, Fn<T, Object> fn) {
        return useCondition ? isNotNull(fn) : this;
    }

    /**
     * 指定字段不为 null
     *
     * @param fn 字段对应的 get 方法引用
     */
    public LambdaExampleWrapper<T> isNotNull(Fn<T, Object> fn) {
        this.current.addCriterion(fn.toColumn() + " IS NOT NULL");
        return this;
    }

    /**
     * 字段 = 值
     *
     * @param useCondition 表达式条件, true 使用,false 不使用
     * @param fn           字段对应的 get 方法引用
     * @param value        值
     */
    public LambdaExampleWrapper<T> eq(boolean useCondition, Fn<T, Object> fn, Object value) {
        return useCondition ? eq(fn, value) : this;
    }

    /**
     * 字段 = 值
     *
     * @param useCondition 表达式条件, true 使用,false 不使用
     * @param fn           字段对应的 get 方法引用
     * @param supplier     值构造函数
     */
    public LambdaExampleWrapper<T> eq(boolean useCondition, Fn<T, Object> fn, Supplier<Object> supplier) {
        return useCondition ? eq(fn, supplier.get()) : this;
    }

    /**
     * 字段 = 值
     *
     * @param fn    字段对应的 get 方法引用
     * @param value 值
     */
    public LambdaExampleWrapper<T> eq(Fn<T, Object> fn, Object value) {
        this.current.addCriterion(fn.toColumn() + " =", value);
        return this;
    }

    /**
     * 字段 != 值
     *
     * @param useCondition 表达式条件, true 使用,false 不使用
     * @param fn           字段对应的 get 方法引用
     * @param supplier     值构造函数
     */
    public LambdaExampleWrapper<T> ne(boolean useCondition, Fn<T, Object> fn, Supplier<Object> supplier) {
        return useCondition ? ne(fn, supplier.get()) : this;
    }

    /**
     * 字段 != 值
     *
     * @param useCondition 表达式条件, true 使用,false 不使用
     * @param fn           字段对应的 get 方法引用
     * @param value        值
     */
    public LambdaExampleWrapper<T> ne(boolean useCondition, Fn<T, Object> fn, Object value) {
        return useCondition ? ne(fn, value) : this;
    }

    /**
     * 字段 != 值
     *
     * @param fn    字段对应的 get 方法引用
     * @param value 值
     */
    public LambdaExampleWrapper<T> ne(Fn<T, Object> fn, Object value) {
        this.current.addCriterion(fn.toColumn() + " <>", value);
        return this;
    }

    /**
     * 字段 > 值
     *
     * @param useCondition 表达式条件, true 使用,false 不使用
     * @param fn           字段对应的 get 方法引用
     * @param supplier     值构造函数
     */
    public LambdaExampleWrapper<T> gt(boolean useCondition, Fn<T, Object> fn, Supplier<Object> supplier) {
        return useCondition ? gt(fn, supplier.get()) : this;
    }

    /**
     * 字段 > 值
     *
     * @param useCondition 表达式条件, true 使用,false 不使用
     * @param fn           字段对应的 get 方法引用
     * @param value        值
     */
    public LambdaExampleWrapper<T> gt(boolean useCondition, Fn<T, Object> fn, Object value) {
        return useCondition ? gt(fn, value) : this;
    }

    /**
     * 字段 > 值
     *
     * @param fn    字段对应的 get 方法引用
     * @param value 值
     */
    public LambdaExampleWrapper<T> gt(Fn<T, Object> fn, Object value) {
        this.current.addCriterion(fn.toColumn() + " >", value);
        return this;
    }

    /**
     * 字段 >= 值
     *
     * @param useCondition 表达式条件, true 使用,false 不使用
     * @param fn           字段对应的 get 方法引用
     * @param supplier     值构造函数
     */
    public LambdaExampleWrapper<T> ge(boolean useCondition, Fn<T, Object> fn, Supplier<Object> supplier) {
        return useCondition ? ge(fn, supplier.get()) : this;
    }

    /**
     * 字段 >= 值
     *
     * @param useCondition 表达式条件, true 使用,false 不使用
     * @param fn           字段对应的 get 方法引用
     * @param value        值
     */
    public LambdaExampleWrapper<T> ge(boolean useCondition, Fn<T, Object> fn, Object value) {
        return useCondition ? ge(fn, value) : this;
    }

    /**
     * 字段 >= 值
     *
     * @param fn    字段对应的 get 方法引用
     * @param value 值
     */
    public LambdaExampleWrapper<T> ge(Fn<T, Object> fn, Object value) {
        this.current.addCriterion(fn.toColumn() + " >=", value);
        return this;
    }

    /**
     * 字段 < 值
     *
     * @param useCondition 表达式条件, true 使用,false 不使用
     * @param fn           字段对应的 get 方法引用
     */
    public LambdaExampleWrapper<T> lt(boolean useCondition, Fn<T, Object> fn, Supplier<Object> supplier) {
        return useCondition ? lt(fn, supplier.get()) : this;
    }

    /**
     * 字段 < 值
     *
     * @param useCondition 表达式条件, true 使用,false 不使用
     * @param fn           字段对应的 get 方法引用
     * @param value        值
     */
    public LambdaExampleWrapper<T> lt(boolean useCondition, Fn<T, Object> fn, Object value) {
        return useCondition ? lt(fn, value) : this;
    }

    /**
     * 字段 < 值
     *
     * @param fn    字段对应的 get 方法引用
     * @param value 值
     */
    public LambdaExampleWrapper<T> lt(Fn<T, Object> fn, Object value) {
        this.current.addCriterion(fn.toColumn() + " <", value);
        return this;
    }

    /**
     * 字段 <= 值
     *
     * @param useCondition 表达式条件, true 使用,false 不使用
     * @param fn           字段对应的 get 方法引用
     * @param value        值
     */
    public LambdaExampleWrapper<T> le(boolean useCondition, Fn<T, Object> fn, Object value) {
        return useCondition ? le(fn, value) : this;
    }

    /**
     * 字段 <= 值
     *
     * @param useCondition 表达式条件, true 使用,false 不使用
     * @param fn           字段对应的 get 方法引用
     * @param supplier     值构造函数
     */
    public LambdaExampleWrapper<T> le(boolean useCondition, Fn<T, Object> fn, Supplier<Object> supplier) {
        return useCondition ? le(fn, supplier.get()) : this;
    }

    /**
     * 字段 <= 值
     *
     * @param fn    字段对应的 get 方法引用
     * @param value 值
     */
    public LambdaExampleWrapper<T> le(Fn<T, Object> fn, Object value) {
        this.current.addCriterion(fn.toColumn() + " <=", value);
        return this;
    }

    /**
     * 字段 in (值集合)
     *
     * @param useCondition 表达式条件, true 使用,false 不使用
     * @param fn           字段对应的 get 方法引用
     * @param values       值集合
     */
    @SuppressWarnings("rawtypes")
    public LambdaExampleWrapper<T> in(boolean useCondition, Fn<T, Object> fn, Iterable values) {
        return useCondition ? in(fn, values) : this;
    }

    /**
     * 字段 in (值集合)
     *
     * @param useCondition 表达式条件, true 使用,false 不使用
     * @param fn           字段对应的 get 方法引用
     * @param supplier     值集合构造函数
     */
    @SuppressWarnings("rawtypes")
    public LambdaExampleWrapper<T> in(boolean useCondition, Fn<T, Object> fn, Supplier<Iterable> supplier) {
        return useCondition ? in(fn, supplier.get()) : this;
    }

    /**
     * 字段 in (值集合)
     *
     * @param fn     字段对应的 get 方法引用
     * @param values 值集合
     */
    @SuppressWarnings("rawtypes")
    public LambdaExampleWrapper<T> in(Fn<T, Object> fn, Iterable values) {
        this.current.addCriterion(fn.toColumn() + " IN", values);
        return this;
    }

    /**
     * 字段 not in (值集合)
     *
     * @param useCondition 表达式条件, true 使用,false 不使用
     * @param fn           字段对应的 get 方法引用
     * @param values       值集合
     */
    @SuppressWarnings("rawtypes")
    public LambdaExampleWrapper<T> notIn(boolean useCondition, Fn<T, Object> fn, Iterable values) {
        return useCondition ? notIn(fn, values) : this;
    }

    /**
     * 字段 not in (值集合)
     *
     * @param useCondition 表达式条件, true 使用,false 不使用
     * @param fn           字段对应的 get 方法引用
     * @param supplier     值集合构造函数
     */
    @SuppressWarnings("rawtypes")
    public LambdaExampleWrapper<T> notIn(boolean useCondition, Fn<T, Object> fn, Supplier<Iterable> supplier) {
        return useCondition ? notIn(fn, supplier.get()) : this;
    }

    /**
     * 字段 not in (值集合)
     *
     * @param fn     字段对应的 get 方法引用
     * @param values 值集合
     */
    @SuppressWarnings("rawtypes")
    public LambdaExampleWrapper<T> notIn(Fn<T, Object> fn, Iterable values) {
        this.current.addCriterion(fn.toColumn() + " NOT IN", values);
        return this;
    }

    /**
     * 字段 between value1 and value 2
     *
     * @param useCondition 表达式条件, true 使用,false 不使用
     * @param fn           字段对应的 get 方法引用
     * @param value1       值1
     * @param value2       值2
     */
    public LambdaExampleWrapper<T> between(boolean useCondition, Fn<T, Object> fn, Object value1, Object value2) {
        return useCondition ? between(fn, value1, value2) : this;
    }

    /**
     * 字段 between value1 and value 2
     *
     * @param useCondition 表达式条件, true 使用,false 不使用
     * @param fn           字段对应的 get 方法引用
     * @param supplier1    值1构造函数
     * @param supplier2    值2构造函数
     */
    public LambdaExampleWrapper<T> between(boolean useCondition, Fn<T, Object> fn, Supplier<Object> supplier1, Supplier<Object> supplier2) {
        return useCondition ? between(fn, supplier1.get(), supplier2.get()) : this;
    }

    /**
     * 字段 between value1 and value 2
     *
     * @param fn     字段对应的 get 方法引用
     * @param value1 值1
     * @param value2 值2
     */
    public LambdaExampleWrapper<T> between(Fn<T, Object> fn, Object value1, Object value2) {
        this.current.addCriterion(fn.toColumn() + " BETWEEN", value1, value2);
        return this;
    }

    /**
     * 字段 not between value1 and value 2
     *
     * @param useCondition 表达式条件, true 使用,false 不使用
     * @param fn           字段对应的 get 方法引用
     * @param value1       值1
     * @param value2       值2
     */
    public LambdaExampleWrapper<T> notBetween(boolean useCondition, Fn<T, Object> fn, Object value1, Object value2) {
        return useCondition ? notBetween(fn, value1, value2) : this;
    }

    /**
     * 字段 not between value1 and value 2
     *
     * @param useCondition 表达式条件, true 使用,false 不使用
     * @param fn           字段对应的 get 方法引用
     * @param supplier1    值1构造函数
     * @param supplier2    值2构造函数
     */
    public LambdaExampleWrapper<T> notBetween(boolean useCondition, Fn<T, Object> fn, Supplier<Object> supplier1, Supplier<Object> supplier2) {
        return useCondition ? notBetween(fn, supplier1.get(), supplier2.get()) : this;
    }

    /**
     * 字段 not between value1 and value 2
     *
     * @param fn     字段对应的 get 方法引用
     * @param value1 值1
     * @param value2 值2
     */
    public LambdaExampleWrapper<T> notBetween(Fn<T, Object> fn, Object value1, Object value2) {
        this.current.addCriterion(fn.toColumn() + " NOT BETWEEN", value1, value2);
        return this;
    }

    /**
     * 字段 like %值%
     *
     * @param useCondition 表达式条件, true 使用,false 不使用
     * @param fn           字段对应的 get 方法引用
     * @param value        值,两侧自动添加 %
     */
    public LambdaExampleWrapper<T> contains(boolean useCondition, Fn<T, Object> fn, String value) {
        return useCondition ? contains(fn, value) : this;
    }

    /**
     * 字段 like %值%
     *
     * @param useCondition 表达式条件, true 使用,false 不使用
     * @param fn           字段对应的 get 方法引用
     * @param supplier     值构造函数,两侧自动添加 %
     */
    public LambdaExampleWrapper<T> contains(boolean useCondition, Fn<T, Object> fn, Supplier<String> supplier) {
        return useCondition ? contains(fn, supplier.get()) : this;
    }

    /**
     * 字段 like %值%
     *
     * @param fn    字段对应的 get 方法引用
     * @param value 值,两侧自动添加 %
     */
    public LambdaExampleWrapper<T> contains(Fn<T, Object> fn, String value) {
        this.current.addCriterion(fn.toColumn() + "  LIKE", "%" + value + "%");
        return this;
    }

    /**
     * 字段 like 值%,匹配 value 为前缀的值
     *
     * @param useCondition 表达式条件, true 使用,false 不使用
     * @param fn           字段对应的 get 方法引用
     * @param value        值,右侧自动添加 %
     */
    public LambdaExampleWrapper<T> startsWith(boolean useCondition, Fn<T, Object> fn, String value) {
        return useCondition ? startsWith(fn, value) : this;
    }

    /**
     * 字段 like 值%,匹配 value 为前缀的值
     *
     * @param useCondition 表达式条件, true 使用,false 不使用
     * @param fn           字段对应的 get 方法引用
     * @param supplier     值构造函数,右侧自动添加 %
     */
    public LambdaExampleWrapper<T> startsWith(boolean useCondition, Fn<T, Object> fn, Supplier<String> supplier) {
        return useCondition ? startsWith(fn, supplier.get()) : this;
    }

    /**
     * 字段 like 值%,匹配 value 为前缀的值
     *
     * @param fn    字段对应的 get 方法引用
     * @param value 值,右侧自动添加 %
     */
    public LambdaExampleWrapper<T> startsWith(Fn<T, Object> fn, String value) {
        this.current.addCriterion(fn.toColumn() + "  LIKE", value + "%");
        return this;
    }

    /**
     * 字段 like %值,匹配 value 为后缀的值
     *
     * @param useCondition 表达式条件, true 使用,false 不使用
     * @param fn           字段对应的 get 方法引用
     * @param value        值,左侧自动添加 %
     */
    public LambdaExampleWrapper<T> endsWith(boolean useCondition, Fn<T, Object> fn, String value) {
        return useCondition ? endsWith(fn, value) : this;
    }

    /**
     * 字段 like %值,匹配 value 为后缀的值
     *
     * @param useCondition 表达式条件, true 使用,false 不使用
     * @param fn           字段对应的 get 方法引用
     * @param supplier     值构造函数,左侧自动添加 %
     */
    public LambdaExampleWrapper<T> endsWith(boolean useCondition, Fn<T, Object> fn, Supplier<String> supplier) {
        return useCondition ? endsWith(fn, supplier.get()) : this;
    }

    /**
     * 字段 like %值,匹配 value 为后缀的值
     *
     * @param fn    字段对应的 get 方法引用
     * @param value 值,左侧自动添加 %
     */
    public LambdaExampleWrapper<T> endsWith(Fn<T, Object> fn, String value) {
        this.current.addCriterion(fn.toColumn() + "  LIKE", "%" + value);
        return this;
    }

    /**
     * 字段 like 值
     *
     * @param useCondition 表达式条件, true 使用,false 不使用
     * @param fn           字段对应的 get 方法引用
     * @param value        值,需要指定 '%'(多个), '_'(单个) 模糊匹配
     */
    public LambdaExampleWrapper<T> like(boolean useCondition, Fn<T, Object> fn, String value) {
        return useCondition ? like(fn, value) : this;
    }

    /**
     * 字段 like 值
     *
     * @param useCondition 表达式条件, true 使用,false 不使用
     * @param fn           字段对应的 get 方法引用
     * @param supplier     值构造函数,需要指定 '%'(多个), '_'(单个) 模糊匹配
     */
    public LambdaExampleWrapper<T> like(boolean useCondition, Fn<T, Object> fn, Supplier<String> supplier) {
        return useCondition ? like(fn, supplier.get()) : this;
    }

    /**
     * 字段 like 值
     *
     * @param fn    字段对应的 get 方法引用
     * @param value 值,需要指定 '%'(多个), '_'(单个) 模糊匹配
     */
    public LambdaExampleWrapper<T> like(Fn<T, Object> fn, String value) {
        this.current.addCriterion(fn.toColumn() + "  LIKE", value);
        return this;
    }

    /**
     * 字段 not like 值
     *
     * @param useCondition 表达式条件, true 使用,false 不使用
     * @param fn           字段对应的 get 方法引用
     * @param value        值,需要指定 % 模糊匹配
     */
    public LambdaExampleWrapper<T> notLike(boolean useCondition, Fn<T, Object> fn, String value) {
        return useCondition ? notLike(fn, value) : this;
    }

    /**
     * 字段 not like 值
     *
     * @param useCondition 表达式条件, true 使用,false 不使用
     * @param fn           字段对应的 get 方法引用
     * @param supplier     值构造函数,需要指定 % 模糊匹配
     */
    public LambdaExampleWrapper<T> notLike(boolean useCondition, Fn<T, Object> fn, Supplier<String> supplier) {
        return useCondition ? notLike(fn, supplier.get()) : this;
    }

    /**
     * 字段 not like 值
     *
     * @param fn    字段对应的 get 方法引用
     * @param value 值,需要指定 % 模糊匹配
     */
    public LambdaExampleWrapper<T> notLike(Fn<T, Object> fn, String value) {
        this.current.addCriterion(fn.toColumn() + "  NOT LIKE", value);
        return this;
    }

    /**
     * 添加任意条件,条件一定是后端使用的,需要自己防止 SQL 注入
     *
     * @param useCondition 表达式条件, true 使用,false 不使用
     * @param condition    任意条件,例如 "length(countryname)<5"
     */
    public LambdaExampleWrapper<T> anyCondition(boolean useCondition, String condition) {
        return useCondition ? anyCondition(condition) : this;
    }

    /**
     * 添加任意条件,条件一定是后端使用的,需要自己防止 SQL 注入
     *
     * @param condition 任意条件,例如 "length(countryname)<5"
     */
    public LambdaExampleWrapper<T> anyCondition(String condition) {
        this.current.andCondition(condition);
        return this;
    }

    /**
     * 手写左边条件,右边用value值
     *
     * @param useCondition 表达式条件, true 使用,false 不使用
     * @param condition    例如 "length(countryname)="
     * @param value        例如 5
     */
    public LambdaExampleWrapper<T> anyCondition(boolean useCondition, String condition, Object value) {
        return useCondition ? anyCondition(condition, value) : this;
    }

    /**
     * 手写左边条件,右边用value值
     *
     * @param useCondition 表达式条件, true 使用,false 不使用
     * @param condition    例如 "length(countryname)="
     * @param supplier     任意条件值的构造函数
     */
    public LambdaExampleWrapper<T> anyCondition(boolean useCondition, String condition, Supplier<Object> supplier) {
        return useCondition ? anyCondition(condition, supplier.get()) : this;
    }

    /**
     * 手写左边条件,右边用value值
     *
     * @param condition 例如 "length(countryname)="
     * @param value     例如 5
     */
    public LambdaExampleWrapper<T> anyCondition(String condition, Object value) {
        this.current.andCondition(condition, value);
        return this;
    }

    /**
     * 嵌套 or 查询,数组多个条件直接使用 or,单个条件中为 and
     *
     * @param orParts 条件块
     */
    @SafeVarargs
    public final LambdaExampleWrapper<T> or(Function<Example.OrCriteria<T>, Example.OrCriteria<T>>... orParts) {
        if (orParts != null && orParts.length > 0) {
            this.current.andOr(Arrays.stream(orParts).map(orPart -> orPart.apply(example.orPart())).collect(Collectors.toList()));
        }
        return this;
    }

    /**
     * 根据当前条件删除
     */
    public int delete() {
        return baseMapper.deleteByExample(example);
    }

    /**
     * 将符合当前查询条件的数据更新为 {@link #set(String)} 和 {@link #set(Fn, Object)} 设置的值
     */
    public int update() {
        Assert.notEmpty(example.getSetValues(), "必须通过 set 方法设置更新的列和值");
        return baseMapper.updateByExampleSetValues(example);
    }

    /**
     * 将符合当前查询条件的数据更新为提供的值, {@link #set(String)} 和 {@link #set(Fn, Object)} 设置的值无效
     *
     * @param t 要更新的值
     */
    public int update(T t) {
        return baseMapper.updateByExample(t, example);
    }

    /**
     * 将符合当前查询条件的数据更新为提供的值,不更新 null 的值
     *
     * @param t 要更新的值
     */
    public int updateSelective(T t) {
        return baseMapper.updateByExampleSelective(t, example);
    }

    /**
     * 根据当前查询条件查询
     */
    public List<T> list() {
        return baseMapper.selectByExample(example);
    }

    /**
     * 根据当前查询条件查询,返回 Stream
     */
    public Stream<T> stream() {
        return list().stream();
    }

    /**
     * 根据当前查询条件查询出一个结果,当存在多个符合条件的结果时会抛出异常 {@link TooManyResultsException}
     */
    public T one() {
        return baseMapper.selectOneByExample(example).orElse(null);
    }

    /**
     * 根据当前查询条件查询出第一个结果,通过 {@link RowBounds} 实现
     */
    public T first() {
        return baseMapper.selectByExample(example, new RowBounds(0, 1)).stream().findFirst().orElse(null);
    }

    /**
     * 根据当前查询条件查询出前 n 个结果,通过 {@link RowBounds} 实现
     *
     * @param n 结果数
     */
    public List<T> top(int n) {
        return baseMapper.selectByExample(example, new RowBounds(0, n));
    }

    /**
     * 查询符合当前条件的结果数
     */
    public long count() {
        return baseMapper.countByExample(example);
    }

    public <RE extends Serializable> List<RE> list(Class<RE> returnClass){
        List<T> ts = list();
        List<RE> res = BeanUtil.copys(ts, returnClass);
        if(ts instanceof Page) {
            Page<RE> pageRes = new Page<>();
            pageRes.addAll(res);
            pageRes.setTotal(((Page<T>) ts).getTotal());
            return pageRes;
        }
        return res;
    }


    public <RE extends Serializable> Page<RE> listPage(Class<RE> returnClass){
        List<T> ts = list();
        List<RE> res = BeanUtil.copys(ts, returnClass);
        Page<RE> pageRes = new Page<>();
        pageRes.addAll(res);
        if(ts instanceof Page) {
            pageRes.setTotal(((Page<T>) ts).getTotal());
            return pageRes;
        }
        return pageRes;
    }

    public <RE extends Serializable> RE one(Class<RE> returnClass){
        T t = one();
        if(t != null) {
            return BeanUtil.copy(t, returnClass);
        }
        return null;
    }

    public <RE extends Serializable> List<RE> top(Integer limit,Class<RE> returnClass){
        List<T> ts = top(limit);
        List<RE> res = BeanUtil.copys(ts, returnClass);
        return res;
    }


    public <RE extends Serializable> RE first(Class<RE> returnClass) {
        T t = first();
        if(t != null) {
            return BeanUtil.copy(t, returnClass);
        }
        return null;
    }

}
View Code

 

 

7、补一个swagger2 to swagger3的注解映射

@ApiModel(value = "") -> @Schema(title = "")
@ApiModelProperty(value = "") -> @Schema(description = "")
@Api(tags = "") -> @Tag(name = "")
@ApiOperation(value = "", tags = {""}) -> @Operation(summary = "", tags = "")

 

热门相关:我有一座冒险屋   本法官萌萌哒   大妆   本法官萌萌哒   有一天偷了你最好朋友的女朋友