天天看點

第 4 章 MybatisPlus 條件構造器第 4 章 MybatisPlus 條件構造器

第 4 章 MybatisPlus 條件構造器

1、CRUD API 的思考

對于 BaseMapper 中基本 CRUD 方法的思考

繼承了 BaseMapper 接口後,我們隻能獲得基本的 CRUD 能力,那麼對于複雜的 SQL 查詢,MybatisPlus 貌似也無能為力,但其實并不是這樣的

現有一個需求,我們需要分頁查詢

t_user

表中,年齡在 18~50 之間性别為男且姓名為 xx的所有使用者,這時候我們該如何實作上述需求呢?

MyBatis:需要在 SQL映射檔案中編寫帶條件查詢的 SQL,并基于 PageHelper插件完成

分頁 . 實作以上一個簡單的需求,往往需要我們做很多重複單調的工作。

MP:依舊不用編寫 SQL語句,MP提供了功能強大的條件構造器

QueryMapper

LambdaQueryWrapper

2、AbstractWrapper

條件構造器的抽象父類:AbstractWrapper

AbstractWrapper

QueryWrapper

(

LambdaQueryWrapper

) 和

UpdateWrapper

(

LambdaUpdateWrapper

) 的父類用于生成 sql 的

where

條件,

entity

屬性也用于生成 sql 的

where

條件

Wrapper

可了解為實體包裝器, 主要用于處理 sql 拼接、排序、實體參數查詢等。

第 4 章 MybatisPlus 條件構造器第 4 章 MybatisPlus 條件構造器
/**
 * 查詢條件封裝
 *
 * @author hubin miemie HCL
 * @since 2017-05-26
 */
@SuppressWarnings({"serial", "unchecked"})
public abstract class AbstractWrapper<T, R, Children extends AbstractWrapper<T, R, Children>> extends Wrapper<T>
    implements Compare<Children, R>, Nested<Children, Children>, Join<Children>, Func<Children, R> {

    /**
     * 占位符
     */
    protected final Children typedThis = (Children) this;
    /**
     * 必要度量
     */
    protected AtomicInteger paramNameSeq;
    protected Map<String, Object> paramNameValuePairs;
    protected SharedString lastSql;
    /**
     * SQL注釋
     */
    protected SharedString sqlComment;
    /**
     * SQL起始語句
     */
    protected SharedString sqlFirst;
    /**
     * ß
     * 資料庫表映射實體類
     */
    private T entity;
    protected MergeSegments expression;
    /**
     * 實體類型(主要用于确定泛型以及取TableInfo緩存)
     */
    private Class<T> entityClass;

    @Override
    public T getEntity() {
        return entity;
    }

    public Children setEntity(T entity) {
        this.entity = entity;
        return typedThis;
    }
           
allEq

全部eq(或個别isNull)

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

個别參數說明

params

:

key

為資料庫字段名,

value

為字段值

null2IsNull

: 為

true

則在

map

value

null

時調用 isNull 方法,為

false

時則忽略

value

null

的字段

例子

  • 例1:

    allEq({id:1,name:"老王",age:null})

    —>

    id = 1 and name = '老王' and age is null

  • 例2:

    allEq({id:1,name:"老王",age:null}, false)

    —>

    id = 1 and name = '老王'

eq
eq(R column, Object val)
eq(boolean condition, R column, Object val)
           
  • 等于 =
  • 例:

    eq("name", "老王")

    —>

    name = '老王'

ne
ne(R column, Object val)
ne(boolean condition, R column, Object val)
           
  • 不等于 <>
  • 例:

    ne("name", "老王")

    —>

    name <> '老王'

gt
gt(R column, Object val)
gt(boolean condition, R column, Object val)
           
  • 大于 >
  • 例:

    gt("age", 18)

    —>

    age > 18

ge
ge(R column, Object val)
ge(boolean condition, R column, Object val)
           
  • 大于等于 >=
  • 例:

    ge("age", 18)

    —>

    age >= 18

lt
lt(R column, Object val)
lt(boolean condition, R column, Object val)
           
  • 小于 <
  • 例:

    lt("age", 18)

    —>

    age < 18

le
le(R column, Object val)
le(boolean condition, R column, Object val)
           
  • 小于等于 <=
  • 例:

    le("age", 18)

    —>

    age <= 18

between
between(R column, Object val1, Object val2)
between(boolean condition, R column, Object val1, Object val2)
           
  • BETWEEN 值1 AND 值2
  • 例:

    between("age", 18, 30)

    —>

    age between 18 and 30

notBetween
notBetween(R column, Object val1, Object val2)
notBetween(boolean condition, R column, Object val1, Object val2)
           
  • NOT BETWEEN 值1 AND 值2
  • 例:

    notBetween("age", 18, 30)

    —>

    age not between 18 and 30

like
like(R column, Object val)
like(boolean condition, R column, Object val)
           
  • LIKE ‘%值%’
  • 例:

    like("name", "王")

    —>

    name like '%王%'

notLike
notLike(R column, Object val)
notLike(boolean condition, R column, Object val)
           
  • NOT LIKE ‘%值%’
  • 例:

    notLike("name", "王")

    —>

    name not like '%王%'

likeLeft
likeLeft(R column, Object val)
likeLeft(boolean condition, R column, Object val)
           
  • LIKE ‘%值’
  • 例:

    likeLeft("name", "王")

    —>

    name like '%王'

leftRight
likeRight(R column, Object val)
likeRight(boolean condition, R column, Object val)
           
  • LIKE ‘值%’
  • 例:

    likeRight("name", "王")

    —>

    name like '王%'

isNull
isNull(R column)
isNull(boolean condition, R column)
           
  • 字段 IS NULL
  • 例:

    isNull("name")

    —>

    name is null

isNotNull
isNotNull(R column)
isNotNull(boolean condition, R column)
           
  • 字段 IS NOT NULL
  • 例:

    isNotNull("name")

    —>

    name is not null

in
in(R column, Collection<?> value)
in(boolean condition, R column, Collection<?> value)
           
  • 字段 IN (value.get(0), value.get(1), …)
  • 例:

    in("age",{1,2,3})

    —>

    age in (1,2,3)

in(R column, Object... values)
in(boolean condition, R column, Object... values)
           
  • 字段 IN (v0, v1, …)
  • 例:

    in("age", 1, 2, 3)

    —>

    age in (1,2,3)

notIn
notIn(R column, Collection<?> value)
notIn(boolean condition, R column, Collection<?> value)
           
  • 字段 NOT IN (value.get(0), value.get(1), …)
  • 例:

    notIn("age",{1,2,3})

    —>

    age not in (1,2,3)

notIn(R column, Object... values)
notIn(boolean condition, R column, Object... values)
           
  • 字段 NOT IN (v0, v1, …)
  • 例:

    notIn("age", 1, 2, 3)

    —>

    age not in (1,2,3)

inSql
inSql(R column, String inValue)
inSql(boolean condition, R column, String inValue)
           
  • 字段 IN ( sql語句 )
  • 例:

    inSql("age", "1,2,3,4,5,6")

    —>

    age in (1,2,3,4,5,6)

  • 例:

    inSql("id", "select id from table where id < 3")

    —>

    id in (select id from table where id < 3)

notInSql
notInSql(R column, String inValue)
notInSql(boolean condition, R column, String inValue)
           
  • 字段 NOT IN ( sql語句 )
  • 例:

    notInSql("age", "1,2,3,4,5,6")

    —>

    age not in (1,2,3,4,5,6)

  • 例:

    notInSql("id", "select id from table where id < 3")

    —>

    id not in (select id from table where id < 3)

groupBy
groupBy(R... columns)
groupBy(boolean condition, R... columns)
           
  • 分組:GROUP BY 字段, …
  • 例:

    groupBy("id", "name")

    —>

    group by id,name

orderByAsc
orderByAsc(R... columns)
orderByAsc(boolean condition, R... columns)
           
  • 排序:ORDER BY 字段, … ASC
  • 例:

    orderByAsc("id", "name")

    —>

    order by id ASC,name ASC

orderByDesc
orderByDesc(R... columns)
orderByDesc(boolean condition, R... columns)
           
  • 排序:ORDER BY 字段, … DESC
  • 例:

    orderByDesc("id", "name")

    —>

    order by id DESC,name DESC

orderBy
  • 排序:ORDER BY 字段, …
  • 例:

    orderBy(true, true, "id", "name")

    —>

    order by id ASC,name ASC

having
having(String sqlHaving, Object... params)
having(boolean condition, String sqlHaving, Object... params)
           
  • HAVING ( sql語句 )
  • 例:

    having("sum(age) > 10")

    —>

    having sum(age) > 10

  • 例:

    having("sum(age) > {0}", 11)

    —>

    having sum(age) > 11

func
func(Consumer<Children> consumer)
func(boolean condition, Consumer<Children> consumer)
           
  • func 方法(主要友善在出現if…else下調用不同方法能不斷鍊)
  • 例:

    func(i -> if(true) {i.eq("id", 1)} else {i.ne("id", 1)})

or
or()
or(boolean condition)
           
  • 拼接 OR

注意事項:主動調用

or

表示緊接着下一個方法不是用

and

連接配接!(不調用

or

則預設為使用

and

連接配接)

  • 例:

    eq("id",1).or().eq("name","老王")

    —>

    id = 1 or name = '老王'

or(Consumer<Param> consumer)
or(boolean condition, Consumer<Param> consumer)
           
  • OR 嵌套
  • 例:

    or(i -> i.eq("name", "李白").ne("status", "活着"))

    —>

    or (name = '李白' and status <> '活着')

and
and(Consumer<Param> consumer)
and(boolean condition, Consumer<Param> consumer)
           
  • AND 嵌套
  • 例:

    and(i -> i.eq("name", "李白").ne("status", "活着"))

    —>

    and (name = '李白' and status <> '活着')

nested
nested(Consumer<Param> consumer)
nested(boolean condition, Consumer<Param> consumer)
           
  • 正常嵌套 不帶 AND 或者 OR
  • 例:

    nested(i -> i.eq("name", "李白").ne("status", "活着"))

    —>

    (name = '李白' and status <> '活着')

apply
apply(String applySql, Object... params)
apply(boolean condition, String applySql, Object... params)
           
  • 拼接 sql

注意事項:該方法可用于資料庫函數 動态入參的

params

對應前面

applySql

内部的

{index}

部分.這樣是不會有sql注入風險的,反之會有!

  • 例:

    apply("id = 1")

    —>

    id = 1

  • 例:

    apply("date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")

    —>

    date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")

  • 例:

    apply("date_format(dateColumn,'%Y-%m-%d') = {0}", "2008-08-08")

    —>

    date_format(dateColumn,'%Y-%m-%d') = '2008-08-08'")

last
last(String lastSql)
last(boolean condition, String lastSql)
           
  • 無視優化規則直接拼接到 sql 的最後

注意事項:隻能調用一次,多次調用以最後一次為準 有sql注入的風險,請謹慎使用

  • 例:

    last("limit 1")

exists
exists(String existsSql)
exists(boolean condition, String existsSql)
           
  • 拼接 EXISTS ( sql語句 )
  • 例:

    exists("select id from table where age = 1")

    —>

    exists (select id from table where age = 1)

notExists
notExists(String notExistsSql)
notExists(boolean condition, String notExistsSql)
           
  • 拼接 NOT EXISTS ( sql語句 )
  • 例:

    notExists("select id from table where age = 1")

    —>

    not exists (select id from table where age = 1)

3、QueryWrapper

1、AbstractWrapper 的實作類之一:QueryWrapper

QueryWrapper

繼承自

AbstractWrapper

,自身的内部屬性

entity

也用于生成

where

條件

LambdaQueryWrapper

,可以通過

new QueryWrapper().lambda()

方法擷取

QueryWrapper

使用的是資料庫字段,不是 Java屬性!

/**
 * Entity 對象封裝操作類
 *
 * @author hubin miemie HCL
 * @since 2018-05-25
 */
@SuppressWarnings("serial")
public class QueryWrapper<T> extends AbstractWrapper<T, String, QueryWrapper<T>>
    implements Query<QueryWrapper<T>, T, String> {

    /**
     * 查詢字段
     */
    private final SharedString sqlSelect = new SharedString();

    public QueryWrapper() {
        this(null);
    }

    public QueryWrapper(T entity) {
        super.setEntity(entity);
        super.initNeed();
    }

    public QueryWrapper(T entity, String... columns) {
        super.setEntity(entity);
        super.initNeed();
        this.select(columns);
    }
           

select

select(String... sqlSelect)
select(Predicate<TableFieldInfo> predicate)
select(Class<T> entityClass, Predicate<TableFieldInfo> predicate)
           
  • 設定查詢字段

說明: 以上方法分為兩類. 第二類方法為: 過濾查詢字段(主鍵除外), 入參不包含 class 的調用前需要

wrapper

内的

entity

屬性有值! 這兩類方法重複調用以最後一次為準

  • 例:

    select("id", "name", "age")

  • 例:

    select(i -> i.getProperty().startsWith("test"))

2、AbstractWrapper 的實作類之一:LambdaQueryWrapper

QueryWrapper

中可以擷取到擷取

LambdaQueryWrapper

對象,

LambdaQueryWrapper

支援使用

類名 : getXxx()

的方式構造 SQL 語句

/**
 * 傳回一個支援 lambda 函數寫法的 wrapper
 */
public LambdaQueryWrapper<T> lambda() {
    return new LambdaQueryWrapper<>(getEntity(), getEntityClass(), sqlSelect, paramNameSeq, paramNameValuePairs,
        expression, lastSql, sqlComment, sqlFirst);
}
           

4、UpdateWrapper

1、AbstractWrapper 的實作類之一:UpdateWrapper

UpdateWrapper

繼承自

AbstractWrapper

,自身的内部屬性

entity

也用于生成 where 條件

LambdaUpdateWrapper

, 可以通過

new UpdateWrapper().lambda()

方法擷取

UpdateWrapper

使用的是資料庫字段,不是 Java屬性!

/**
 * Update 條件封裝
 *
 * @author hubin miemie HCL
 * @since 2018-05-30
 */
@SuppressWarnings("serial")
public class UpdateWrapper<T> extends AbstractWrapper<T, String, UpdateWrapper<T>>
    implements Update<UpdateWrapper<T>, String> {

    /**
     * SQL 更新字段内容,例如:name='1', age=2
     */
    private final List<String> sqlSet;

    public UpdateWrapper() {
        // 如果無參構造函數,請注意實體 NULL 情況 SET 必須有否則 SQL 異常
        this(null);
    }

    public UpdateWrapper(T entity) {
        super.setEntity(entity);
        super.initNeed();
        this.sqlSet = new ArrayList<>();
    }
           
set
set(String column, Object val)
set(boolean condition, String column, Object val)
           
  • SQL SET 字段
  • 例:

    set("name", "老李頭")

  • 例:

    set("name", "")

    —>資料庫字段值變為空字元串
  • 例:

    set("name", null)

    —>資料庫字段值變為

    null

setSql
  • 設定 SET 部分 SQL
  • 例:

    setSql("name = '老李頭'")

2、AbstractWrapper 的實作類之一:LambdaUpdateWrapper

UpdateWrapper

中可以擷取到

LambdaUpdateWrapper

對象,

LambdaUpdateWrapper

支援使用

類名 : getXxx()

的方式構造 SQL 語句

/**
 * 傳回一個支援 lambda 函數寫法的 wrapper
 */
public LambdaUpdateWrapper<T> lambda() {
    return new LambdaUpdateWrapper<>(getEntity(), getEntityClass(), sqlSet, paramNameSeq, paramNameValuePairs,
        expression, lastSql, sqlComment, sqlFirst);
}
           

5、Wrapper 原理分析

為什麼支援鍊式調用?

Wrapper 條件構造器支援鍊式調用,比如:

lambdaQuery().eq(Entity::getId, value).one();

update().eq("id", value).remove();

這樣的形式

AbstractWrapper

類中定義的條件構造方法,傳回值都會

Children

類型。

Children

AbstractWrapper

類的泛型:

Children extends AbstractWrapper<T, R, Children>> extends Wrapper<T>

喲,擱這兒套娃呢?不過我們知道

Children

繼承了

AbstractWrapper

抽象類就行,是以調用條件構造方法傳回的仍然是

AbstractWrapper

類型的對象,這就是解釋了為什麼

AbstractWrapper

支援鍊式調用

/**
 * 查詢條件封裝
 *
 * @author hubin miemie HCL
 * @since 2017-05-26
 */
@SuppressWarnings({"serial", "unchecked"})
public abstract class AbstractWrapper<T, R, Children extends AbstractWrapper<T, R, Children>> extends Wrapper<T>
    implements Compare<Children, R>, Nested<Children, Children>, Join<Children>, Func<Children, R> {
	
    @Override
    public Children eq(boolean condition, R column, Object val) {
        return addCondition(condition, column, EQ, val);
    }

    @Override
    public Children ne(boolean condition, R column, Object val) {
        return addCondition(condition, column, NE, val);
    }

    @Override
    public Children gt(boolean condition, R column, Object val) {
        return addCondition(condition, column, GT, val);
    }

    @Override
    public Children ge(boolean condition, R column, Object val) {
        return addCondition(condition, column, GE, val);
    }

    @Override
    public Children lt(boolean condition, R column, Object val) {
        return addCondition(condition, column, LT, val);
    }

    @Override
    public Children le(boolean condition, R column, Object val) {
        return addCondition(condition, column, LE, val);
    }

    @Override
    public Children like(boolean condition, R column, Object val) {
        return likeValue(condition, LIKE, column, val, SqlLike.DEFAULT);
    }

    @Override
    public Children notLike(boolean condition, R column, Object val) {
        return likeValue(condition, NOT_LIKE, column, val, SqlLike.DEFAULT);
    }

           

舉個栗子:

QueryWrapper

繼承了

AbstractWrapper

抽象父類,其

Children

泛型為

QueryWrapper<T>

,是以調用

QueryWrapper

的條件構造方法傳回的是

QueryWrapper

對象,那肯定也能再繼續調用條件構造方法啦~~~

/**
 * Entity 對象封裝操作類
 *
 * @author hubin miemie HCL
 * @since 2018-05-25
 */
@SuppressWarnings("serial")
public class QueryWrapper<T> extends AbstractWrapper<T, String, QueryWrapper<T>>
    implements Query<QueryWrapper<T>, T, String> {
           
為什麼 LambdaQueryWrapper 可以傳入類的 getter 方法?

LambdaQueryWrapper

的父類為

AbstractLambdaWrapper

,在

AbstractLambdaWrapper

父類中定義了

columnsToString()

方法:用于将 getter 方法對應的字段名轉換為資料庫列名

columnsToString()

方法最終會調用

getColumn()

方法:通過

String fieldName = PropertyNamer.methodToProperty(lambda.getImplMethodName());

将 lambda 表達式轉換為字段名

/**
 * Lambda 文法使用 Wrapper
 * <p>統一處了解析 lambda 擷取 column</p>
 *
 * @author hubin miemie HCL
 * @since 2017-05-26
 */
@SuppressWarnings("serial")
public abstract class AbstractLambdaWrapper<T, Children extends AbstractLambdaWrapper<T, Children>>
    extends AbstractWrapper<T, SFunction<T, ?>, Children> {

    private Map<String, ColumnCache> columnMap = null;
    private boolean initColumnMap = false;

    @SuppressWarnings("unchecked")
    @Override
    protected String columnsToString(SFunction<T, ?>... columns) {
        return columnsToString(true, columns);
    }

    @SuppressWarnings("unchecked")
    protected String columnsToString(boolean onlyColumn, SFunction<T, ?>... columns) {
        return Arrays.stream(columns).map(i -> columnToString(i, onlyColumn)).collect(joining(StringPool.COMMA));
    }

    @Override
    protected String columnToString(SFunction<T, ?> column) {
        return columnToString(column, true);
    }

    protected String columnToString(SFunction<T, ?> column, boolean onlyColumn) {
        return getColumn(LambdaUtils.resolve(column), onlyColumn);
    }

    /**
     * 擷取 SerializedLambda 對應的列資訊,從 lambda 表達式中推測實體類
     * <p>
     * 如果擷取不到列資訊,那麼本次條件組裝将會失敗
     *
     * @param lambda     lambda 表達式
     * @param onlyColumn 如果是,結果: "name", 如果否: "name" as "name"
     * @return 列
     * @throws com.baomidou.mybatisplus.core.exceptions.MybatisPlusException 擷取不到列資訊時抛出異常
     * @see SerializedLambda#getImplClass()
     * @see SerializedLambda#getImplMethodName()
     */
    private String getColumn(SerializedLambda lambda, boolean onlyColumn) {
        Class<?> aClass = lambda.getInstantiatedType();
        tryInitCache(aClass);
        String fieldName = PropertyNamer.methodToProperty(lambda.getImplMethodName());
        ColumnCache columnCache = getColumnCache(fieldName, aClass);
        return onlyColumn ? columnCache.getColumn() : columnCache.getColumnSelect();
    }

    private void tryInitCache(Class<?> lambdaClass) {
        if (!initColumnMap) {
            final Class<T> entityClass = getEntityClass();
            if (entityClass != null) {
                lambdaClass = entityClass;
            }
            columnMap = LambdaUtils.getColumnMap(lambdaClass);
            initColumnMap = true;
        }
        Assert.notNull(columnMap, "can not find lambda cache for this entity [%s]", lambdaClass.getName());
    }

    private ColumnCache getColumnCache(String fieldName, Class<?> lambdaClass) {
        ColumnCache columnCache = columnMap.get(LambdaUtils.formatKey(fieldName));
        Assert.notNull(columnCache, "can not find lambda cache for this property [%s] of entity [%s]",
            fieldName, lambdaClass.getName());
        return columnCache;
    }
}
           

6、擷取 Wrapper 對象

Wrappers 類:擷取各種 Wrapper 對象
  1. public static <T> QueryWrapper<T> query() {

    :擷取

    QueryWrapper

    對象
  2. public static <T> LambdaQueryWrapper<T> lambdaQuery() {

    :擷取

    LambdaQueryWrapper

    對象
  3. public static <T> UpdateWrapper<T> update() {

    :擷取

    UpdateWrapper

    對象
  4. public static <T> LambdaUpdateWrapper<T> lambdaUpdate() {

    :擷取

    LambdaUpdateWrapper

    對象
  5. public static <T> QueryWrapper<T> emptyWrapper() {

    :擷取

    EmptyWrapper

    對象
/**
 * Wrapper 條件構造
 *
 * @author Caratacus
 */
public final class Wrappers {

    /**
     * 空的 EmptyWrapper
     */
    private static final QueryWrapper<?> emptyWrapper = new EmptyWrapper<>();

    private Wrappers() {
        // ignore
    }

    /**
     * 擷取 QueryWrapper&lt;T&gt;
     *
     * @param <T> 實體類泛型
     * @return QueryWrapper&lt;T&gt;
     */
    public static <T> QueryWrapper<T> query() {
        return new QueryWrapper<>();
    }

    /**
     * 擷取 QueryWrapper&lt;T&gt;
     *
     * @param entity 實體類
     * @param <T>    實體類泛型
     * @return QueryWrapper&lt;T&gt;
     */
    public static <T> QueryWrapper<T> query(T entity) {
        return new QueryWrapper<>(entity);
    }

    /**
     * 擷取 LambdaQueryWrapper&lt;T&gt;
     *
     * @param <T> 實體類泛型
     * @return LambdaQueryWrapper&lt;T&gt;
     */
    public static <T> LambdaQueryWrapper<T> lambdaQuery() {
        return new LambdaQueryWrapper<>();
    }

    /**
     * 擷取 LambdaQueryWrapper&lt;T&gt;
     *
     * @param entity 實體類
     * @param <T>    實體類泛型
     * @return LambdaQueryWrapper&lt;T&gt;
     */
    public static <T> LambdaQueryWrapper<T> lambdaQuery(T entity) {
        return new LambdaQueryWrapper<>(entity);
    }

    /**
     * 擷取 LambdaQueryWrapper&lt;T&gt;
     *
     * @param entityClass 實體類class
     * @param <T>         實體類泛型
     * @return LambdaQueryWrapper&lt;T&gt;
     * @since 3.3.1
     */
    public static <T> LambdaQueryWrapper<T> lambdaQuery(Class<T> entityClass) {
        return new LambdaQueryWrapper<>(entityClass);
    }

    /**
     * 擷取 UpdateWrapper&lt;T&gt;
     *
     * @param <T> 實體類泛型
     * @return UpdateWrapper&lt;T&gt;
     */
    public static <T> UpdateWrapper<T> update() {
        return new UpdateWrapper<>();
    }

    /**
     * 擷取 UpdateWrapper&lt;T&gt;
     *
     * @param entity 實體類
     * @param <T>    實體類泛型
     * @return UpdateWrapper&lt;T&gt;
     */
    public static <T> UpdateWrapper<T> update(T entity) {
        return new UpdateWrapper<>(entity);
    }

    /**
     * 擷取 LambdaUpdateWrapper&lt;T&gt;
     *
     * @param <T> 實體類泛型
     * @return LambdaUpdateWrapper&lt;T&gt;
     */
    public static <T> LambdaUpdateWrapper<T> lambdaUpdate() {
        return new LambdaUpdateWrapper<>();
    }

    /**
     * 擷取 LambdaUpdateWrapper&lt;T&gt;
     *
     * @param entity 實體類
     * @param <T>    實體類泛型
     * @return LambdaUpdateWrapper&lt;T&gt;
     */
    public static <T> LambdaUpdateWrapper<T> lambdaUpdate(T entity) {
        return new LambdaUpdateWrapper<>(entity);
    }

    /**
     * 擷取 LambdaUpdateWrapper&lt;T&gt;
     *
     * @param entityClass 實體類class
     * @param <T>         實體類泛型
     * @return LambdaUpdateWrapper&lt;T&gt;
     * @since 3.3.1
     */
    public static <T> LambdaUpdateWrapper<T> lambdaUpdate(Class<T> entityClass) {
        return new LambdaUpdateWrapper<>(entityClass);
    }

    /**
     * 擷取 EmptyWrapper&lt;T&gt;
     *
     * @param <T> 任意泛型
     * @return EmptyWrapper&lt;T&gt;
     * @see EmptyWrapper
     */
    @SuppressWarnings("unchecked")
    public static <T> QueryWrapper<T> emptyWrapper() {
        return (QueryWrapper<T>) emptyWrapper;
    }
           

繼續閱讀