CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-baomidou--mybatis-plus

MyBatis-Plus is an enhanced toolkit for MyBatis providing CRUD operations, query wrappers, pagination, code generation, and Spring Boot integration.

Pending
Overview
Eval results
Files

query-building.mddocs/

Query Building

MyBatis-Plus provides flexible query wrapper classes for building complex SQL queries with both string-based and lambda-style condition APIs, supporting all common SQL operations with type safety and fluent interfaces.

Capabilities

QueryWrapper

String-based query wrapper for building SQL conditions using column names.

/**
 * Query wrapper for building SQL conditions with column names
 * @param <T> Entity type
 */
public class QueryWrapper<T> extends AbstractWrapper<T, String, QueryWrapper<T>>
    implements Query<QueryWrapper<T>, T, String> {
    
    // Equality conditions
    public QueryWrapper<T> eq(String column, Object val);
    public QueryWrapper<T> ne(String column, Object val);
    
    // Comparison conditions  
    public QueryWrapper<T> gt(String column, Object val);
    public QueryWrapper<T> ge(String column, Object val);
    public QueryWrapper<T> lt(String column, Object val);
    public QueryWrapper<T> le(String column, Object val);
    
    // Range conditions
    public QueryWrapper<T> between(String column, Object val1, Object val2);
    public QueryWrapper<T> notBetween(String column, Object val1, Object val2);
    
    // String matching conditions
    public QueryWrapper<T> like(String column, Object val);
    public QueryWrapper<T> notLike(String column, Object val);
    public QueryWrapper<T> likeLeft(String column, Object val);
    public QueryWrapper<T> likeRight(String column, Object val);
    
    // Null conditions
    public QueryWrapper<T> isNull(String column);
    public QueryWrapper<T> isNotNull(String column);
    
    // Collection conditions
    public QueryWrapper<T> in(String column, Collection<?> values);
    public QueryWrapper<T> notIn(String column, Collection<?> values);
    public QueryWrapper<T> in(String column, Object... values);
    public QueryWrapper<T> notIn(String column, Object... values);
    
    // Subquery conditions
    public QueryWrapper<T> inSql(String column, String inValue);
    public QueryWrapper<T> notInSql(String column, String notInValue);
    
    // Grouping and ordering
    public QueryWrapper<T> groupBy(String... columns);
    public QueryWrapper<T> orderByAsc(String... columns);
    public QueryWrapper<T> orderByDesc(String... columns);
    public QueryWrapper<T> orderBy(boolean condition, boolean isAsc, String... columns);
    
    // Having clause
    public QueryWrapper<T> having(String sqlHaving, Object... params);
    
    // Logical operators
    public QueryWrapper<T> or();
    public QueryWrapper<T> or(boolean condition);
    public QueryWrapper<T> and(Consumer<QueryWrapper<T>> function);
    public QueryWrapper<T> or(Consumer<QueryWrapper<T>> function);
    
    // Nested conditions
    public QueryWrapper<T> nested(Consumer<QueryWrapper<T>> function);
    
    // Custom SQL
    public QueryWrapper<T> apply(String applySql, Object... values);
    public QueryWrapper<T> last(String lastSql);
    
    // Existence conditions
    public QueryWrapper<T> exists(String existsSql);
    public QueryWrapper<T> notExists(String notExistsSql);
    
    // Lambda conversion
    public LambdaQueryWrapper<T> lambda();
    
    // Column selection
    public QueryWrapper<T> select(String... sqlSelect);
    public QueryWrapper<T> select(Class<T> entityClass, Predicate<TableFieldInfo> predicate);
}

LambdaQueryWrapper

Lambda-style query wrapper providing type-safe property references using method references.

/**
 * Lambda query wrapper for type-safe property references
 * @param <T> Entity type
 */
public class LambdaQueryWrapper<T> extends AbstractLambdaWrapper<T, LambdaQueryWrapper<T>>
    implements Query<LambdaQueryWrapper<T>, T, SFunction<T, ?>> {
    
    // Equality conditions
    public LambdaQueryWrapper<T> eq(SFunction<T, ?> fn, Object val);
    public LambdaQueryWrapper<T> ne(SFunction<T, ?> fn, Object val);
    
    // Comparison conditions
    public LambdaQueryWrapper<T> gt(SFunction<T, ?> fn, Object val);
    public LambdaQueryWrapper<T> ge(SFunction<T, ?> fn, Object val);
    public LambdaQueryWrapper<T> lt(SFunction<T, ?> fn, Object val);
    public LambdaQueryWrapper<T> le(SFunction<T, ?> fn, Object val);
    
    // Range conditions
    public LambdaQueryWrapper<T> between(SFunction<T, ?> fn, Object val1, Object val2);
    public LambdaQueryWrapper<T> notBetween(SFunction<T, ?> fn, Object val1, Object val2);
    
    // String matching conditions
    public LambdaQueryWrapper<T> like(SFunction<T, ?> fn, Object val);
    public LambdaQueryWrapper<T> notLike(SFunction<T, ?> fn, Object val);
    public LambdaQueryWrapper<T> likeLeft(SFunction<T, ?> fn, Object val);
    public LambdaQueryWrapper<T> likeRight(SFunction<T, ?> fn, Object val);
    
    // Null conditions
    public LambdaQueryWrapper<T> isNull(SFunction<T, ?> fn);
    public LambdaQueryWrapper<T> isNotNull(SFunction<T, ?> fn);
    
    // Collection conditions
    public LambdaQueryWrapper<T> in(SFunction<T, ?> fn, Collection<?> values);
    public LambdaQueryWrapper<T> notIn(SFunction<T, ?> fn, Collection<?> values);
    public LambdaQueryWrapper<T> in(SFunction<T, ?> fn, Object... values);
    public LambdaQueryWrapper<T> notIn(SFunction<T, ?> fn, Object... values);
    
    // Subquery conditions
    public LambdaQueryWrapper<T> inSql(SFunction<T, ?> fn, String inValue);
    public LambdaQueryWrapper<T> notInSql(SFunction<T, ?> fn, String notInValue);
    
    // Grouping and ordering
    public LambdaQueryWrapper<T> groupBy(SFunction<T, ?>... fns);
    public LambdaQueryWrapper<T> orderByAsc(SFunction<T, ?>... fns);
    public LambdaQueryWrapper<T> orderByDesc(SFunction<T, ?>... fns);
    public LambdaQueryWrapper<T> orderBy(boolean condition, boolean isAsc, SFunction<T, ?>... fns);
    
    // Having clause
    public LambdaQueryWrapper<T> having(String sqlHaving, Object... params);
    
    // Logical operators
    public LambdaQueryWrapper<T> or();
    public LambdaQueryWrapper<T> or(boolean condition);
    public LambdaQueryWrapper<T> and(Consumer<LambdaQueryWrapper<T>> function);
    public LambdaQueryWrapper<T> or(Consumer<LambdaQueryWrapper<T>> function);
    
    // Nested conditions
    public LambdaQueryWrapper<T> nested(Consumer<LambdaQueryWrapper<T>> function);
    
    // Custom SQL
    public LambdaQueryWrapper<T> apply(String applySql, Object... values);
    public LambdaQueryWrapper<T> last(String lastSql);
    
    // Existence conditions
    public LambdaQueryWrapper<T> exists(String existsSql);
    public LambdaQueryWrapper<T> notExists(String notExistsSql);
    
    // Column selection
    public LambdaQueryWrapper<T> select(SFunction<T, ?>... fns);
    public LambdaQueryWrapper<T> select(Class<T> entityClass, Predicate<TableFieldInfo> predicate);
}

UpdateWrapper

String-based update wrapper for building update statements with WHERE conditions.

/**
 * Update wrapper for building update statements with column names
 * @param <T> Entity type
 */
public class UpdateWrapper<T> extends AbstractWrapper<T, String, UpdateWrapper<T>>
    implements Update<UpdateWrapper<T>, String> {
    
    // Set operations
    public UpdateWrapper<T> set(String column, Object val);
    public UpdateWrapper<T> set(boolean condition, String column, Object val);
    public UpdateWrapper<T> setSql(String setSql);
    public UpdateWrapper<T> setSql(boolean condition, String setSql);
    
    // Lambda conversion
    public LambdaUpdateWrapper<T> lambda();
    
    // All QueryWrapper methods are also available for WHERE conditions
    // eq, ne, gt, ge, lt, le, between, like, in, etc.
}

LambdaUpdateWrapper

Lambda-style update wrapper with type-safe property references.

/**
 * Lambda update wrapper for type-safe property references
 * @param <T> Entity type
 */
public class LambdaUpdateWrapper<T> extends AbstractLambdaWrapper<T, LambdaUpdateWrapper<T>>
    implements Update<LambdaUpdateWrapper<T>, SFunction<T, ?>> {
    
    // Set operations
    public LambdaUpdateWrapper<T> set(SFunction<T, ?> fn, Object val);
    public LambdaUpdateWrapper<T> set(boolean condition, SFunction<T, ?> fn, Object val);
    public LambdaUpdateWrapper<T> setSql(String setSql);
    public LambdaUpdateWrapper<T> setSql(boolean condition, String setSql);
    
    // All LambdaQueryWrapper methods are also available for WHERE conditions
    // eq, ne, gt, ge, lt, le, between, like, in, etc.
}

Wrappers Utility

Factory class for creating wrapper instances.

/**
 * Utility class for creating wrapper instances
 */
public final class Wrappers {
    
    /**
     * Create an empty QueryWrapper
     */
    public static <T> QueryWrapper<T> query();
    
    /**
     * Create a QueryWrapper with entity
     */
    public static <T> QueryWrapper<T> query(T entity);
    
    /**
     * Create an empty LambdaQueryWrapper
     */
    public static <T> LambdaQueryWrapper<T> lambdaQuery();
    
    /**
     * Create a LambdaQueryWrapper with entity
     */
    public static <T> LambdaQueryWrapper<T> lambdaQuery(T entity);
    
    /**
     * Create an empty UpdateWrapper
     */
    public static <T> UpdateWrapper<T> update();
    
    /**
     * Create an UpdateWrapper with entity
     */
    public static <T> UpdateWrapper<T> update(T entity);
    
    /**
     * Create an empty LambdaUpdateWrapper
     */
    public static <T> LambdaUpdateWrapper<T> lambdaUpdate();
    
    /**
     * Create a LambdaUpdateWrapper with entity
     */
    public static <T> LambdaUpdateWrapper<T> lambdaUpdate(T entity);
    
    /**
     * Create an empty wrapper (no conditions)
     */
    public static <T> QueryWrapper<T> emptyWrapper();
}

ChainWrappers Utility (MyBatis-Plus 3.5.7+)

Factory class for creating chain wrapper instances, providing fluent chainable query and update operations.

/**
 * Utility class for creating chain wrapper instances
 */
public final class ChainWrappers {
    
    /**
     * Create a LambdaQueryChainWrapper for fluent querying
     * @param mapper BaseMapper instance
     * @return LambdaQueryChainWrapper instance
     */
    public static <T> LambdaQueryChainWrapper<T> lambdaQueryChain(BaseMapper<T> mapper);
    
    /**
     * Create a QueryChainWrapper for fluent querying
     * @param mapper BaseMapper instance
     * @return QueryChainWrapper instance
     */
    public static <T> QueryChainWrapper<T> queryChain(BaseMapper<T> mapper);
    
    /**
     * Create a LambdaUpdateChainWrapper for fluent updating
     * @param mapper BaseMapper instance
     * @return LambdaUpdateChainWrapper instance
     */
    public static <T> LambdaUpdateChainWrapper<T> lambdaUpdateChain(BaseMapper<T> mapper);
    
    /**
     * Create an UpdateChainWrapper for fluent updating
     * @param mapper BaseMapper instance
     * @return UpdateChainWrapper instance
     */
    public static <T> UpdateChainWrapper<T> updateChain(BaseMapper<T> mapper);
}

Usage Examples

Basic Query Conditions:

// String-based QueryWrapper
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("name", "John")
       .gt("age", 18)
       .like("email", "@gmail.com")
       .isNotNull("phone");

List<User> users = userMapper.selectList(wrapper);

// Lambda-based LambdaQueryWrapper (type-safe)
LambdaQueryWrapper<User> lambdaWrapper = new LambdaQueryWrapper<>();
lambdaWrapper.eq(User::getName, "John")
             .gt(User::getAge, 18)
             .like(User::getEmail, "@gmail.com")
             .isNotNull(User::getPhone);

List<User> users = userMapper.selectList(lambdaWrapper);

Complex Logical Conditions:

// AND and OR combinations
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("status", 1)
       .and(w -> w.eq("type", "VIP").or().gt("score", 1000))
       .or(w -> w.eq("level", "ADMIN"));

// Generates: WHERE status = 1 AND (type = 'VIP' OR score > 1000) OR level = 'ADMIN'

// Nested conditions
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(User::getStatus, 1)
       .nested(w -> w.eq(User::getType, "VIP")
                     .or()
                     .gt(User::getScore, 1000));

// Generates: WHERE status = 1 AND (type = 'VIP' OR score > 1000)

Range and Collection Conditions:

// Range conditions
wrapper.between("age", 18, 65)
       .notBetween("score", 0, 60);

// Collection conditions
List<String> cities = Arrays.asList("Beijing", "Shanghai", "Guangzhou");
wrapper.in("city", cities)
       .notIn("status", 0, -1);

// Subquery conditions
wrapper.inSql("dept_id", "SELECT id FROM department WHERE name = 'IT'")
       .notInSql("role_id", "SELECT id FROM role WHERE name = 'GUEST'");

String Matching:

// Different LIKE patterns
wrapper.like("name", "John")           // name LIKE '%John%'
       .likeLeft("email", "gmail.com") // email LIKE '%gmail.com'
       .likeRight("phone", "138")      // phone LIKE '138%'
       .notLike("address", "temp");    // address NOT LIKE '%temp%'

Ordering and Grouping:

// Ordering
wrapper.orderByAsc("create_time")
       .orderByDesc("update_time", "id");

// Dynamic ordering
boolean sortByAge = true;
wrapper.orderBy(sortByAge, true, "age"); // Conditional ascending sort

// Grouping with HAVING
wrapper.select("dept_id", "COUNT(*) as count")
       .groupBy("dept_id")
       .having("COUNT(*) > 5");

Column Selection:

// Select specific columns
wrapper.select("id", "name", "email");

// Lambda column selection
lambdaWrapper.select(User::getId, User::getName, User::getEmail);

// Conditional column selection
wrapper.select(User.class, info -> !info.getColumn().equals("password"));

Update Operations:

// UpdateWrapper for setting values
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.set("status", 1)
             .set("update_time", LocalDateTime.now())
             .eq("id", 123);

userMapper.update(null, updateWrapper);

// LambdaUpdateWrapper (type-safe)
LambdaUpdateWrapper<User> lambdaUpdate = new LambdaUpdateWrapper<>();
lambdaUpdate.set(User::getStatus, 1)
            .set(User::getUpdateTime, LocalDateTime.now())
            .eq(User::getId, 123);

userMapper.update(null, lambdaUpdate);

// Update with entity and conditions
User updateUser = new User();
updateUser.setStatus(1);

UpdateWrapper<User> wrapper = new UpdateWrapper<>();
wrapper.eq("dept_id", 10).gt("age", 25);

userMapper.update(updateUser, wrapper);

Using Wrappers Utility:

// Factory methods for cleaner code
import static com.baomidou.mybatisplus.core.conditions.Wrappers.*;

// Query wrappers
List<User> users = userMapper.selectList(
    query(User.class).eq("status", 1).gt("age", 18)
);

List<User> activeUsers = userMapper.selectList(
    lambdaQuery(User.class).eq(User::getStatus, 1)
                           .gt(User::getAge, 18)
);

// Update wrappers
userMapper.update(null, 
    update(User.class).set("status", 0).eq("id", 123)
);

userMapper.update(null,
    lambdaUpdate(User.class).set(User::getStatus, 0)
                            .eq(User::getId, 123)
);

Custom SQL and Advanced Features:

// Custom SQL fragments
wrapper.apply("DATE_FORMAT(create_time, '%Y-%m') = {0}", "2023-11");

// Raw SQL at the end (use with caution)
wrapper.eq("status", 1).last("LIMIT 10");

// Existence conditions
wrapper.exists("SELECT 1 FROM user_role WHERE user_id = user.id AND role_id = 1")
       .notExists("SELECT 1 FROM user_ban WHERE user_id = user.id");

// Conditional building
String name = getNameParam(); // Could be null
Integer minAge = getMinAgeParam(); // Could be null

wrapper.eq(StringUtils.isNotBlank(name), "name", name)
       .ge(minAge != null, "age", minAge);

Performance Tips:

  • Use LambdaQueryWrapper for type safety and refactoring support
  • Prefer method chaining for readability
  • Use conditional building to avoid null parameter issues
  • Select only needed columns with select() methods
  • Use last() sparingly and never with user input (SQL injection risk)
  • Consider database indexes for frequently used query conditions

Install with Tessl CLI

npx tessl i tessl/maven-com-baomidou--mybatis-plus

docs

active-record.md

annotations.md

code-generation.md

core-crud.md

index.md

pagination.md

plugins.md

query-building.md

service-layer.md

spring-boot.md

tile.json