MyBatis-Flex is an elegant enhancement framework for MyBatis providing type-safe query building, active record patterns, and comprehensive ORM capabilities
—
Type-safe, fluent query building with comprehensive SQL support. The QueryWrapper system provides a powerful, readable way to construct complex SQL queries with full IDE support and compile-time type checking.
Primary query builder class providing fluent API for constructing SQL queries with type safety and IDE auto-completion.
/**
* Fluent query builder for type-safe SQL construction
*/
public class QueryWrapper {
/**
* Create new empty query wrapper
* @return new QueryWrapper instance
*/
public static QueryWrapper create();
/**
* Create query wrapper from entity with non-null fields as conditions
* @param entity entity object
* @return QueryWrapper with entity conditions
*/
public static QueryWrapper create(Object entity);
/**
* Create query wrapper from map with key-value conditions
* @param map condition map
* @return QueryWrapper with map conditions
*/
public static QueryWrapper create(Map<String, Object> map);
/**
* Specify columns to select
* @param queryColumns columns to select
* @return query wrapper for chaining
*/
public QueryWrapper select(QueryColumn... queryColumns);
/**
* Specify columns to select with lambda expressions
* @param lambdaGetters lambda getter methods
* @return query wrapper for chaining
*/
public <T> QueryWrapper select(LambdaGetter<T>... lambdaGetters);
/**
* Select distinct records
* @param queryColumns columns to select
* @return query wrapper for chaining
*/
public QueryWrapper selectDistinct(QueryColumn... queryColumns);
/**
* Specify tables to query from
* @param entityClasses entity classes representing tables
* @return query wrapper for chaining
*/
public QueryWrapper from(Class<?>... entityClasses);
/**
* Add WHERE conditions
* @param queryCondition condition to apply
* @return query wrapper for chaining
*/
public QueryWrapper where(QueryCondition queryCondition);
/**
* Add LEFT JOIN clause
* @param entityClass entity class to join
* @return query wrapper for chaining
*/
public QueryWrapper leftJoin(Class<?> entityClass);
/**
* Add INNER JOIN clause
* @param entityClass entity class to join
* @return query wrapper for chaining
*/
public QueryWrapper innerJoin(Class<?> entityClass);
/**
* Add RIGHT JOIN clause
* @param entityClass entity class to join
* @return query wrapper for chaining
*/
public QueryWrapper rightJoin(Class<?> entityClass);
/**
* Add GROUP BY clause
* @param queryColumns columns to group by
* @return query wrapper for chaining
*/
public QueryWrapper groupBy(QueryColumn... queryColumns);
/**
* Add HAVING clause for group conditions
* @param queryCondition having condition
* @return query wrapper for chaining
*/
public QueryWrapper having(QueryCondition queryCondition);
/**
* Add ORDER BY clause
* @param queryColumns columns to order by
* @return query wrapper for chaining
*/
public QueryWrapper orderBy(QueryColumn... queryColumns);
/**
* Limit number of results
* @param rows maximum number of rows
* @return query wrapper for chaining
*/
public QueryWrapper limit(Number rows);
/**
* Set result offset for pagination
* @param offset number of rows to skip
* @return query wrapper for chaining
*/
public QueryWrapper offset(Number offset);
/**
* Add UNION clause
* @param queryWrapper query to union with
* @return query wrapper for chaining
*/
public QueryWrapper union(QueryWrapper queryWrapper);
/**
* Add UNION ALL clause
* @param queryWrapper query to union with
* @return query wrapper for chaining
*/
public QueryWrapper unionAll(QueryWrapper queryWrapper);
}Basic Query Building:
import static com.mybatisflex.core.query.QueryMethods.*;
// Simple select
QueryWrapper query = QueryWrapper.create()
.select()
.from(User.class)
.where(USER.AGE.ge(18));
// Select specific columns
QueryWrapper query = QueryWrapper.create()
.select(USER.NAME, USER.EMAIL)
.from(User.class)
.where(USER.ACTIVE.eq(true));
// Complex conditions
QueryWrapper query = QueryWrapper.create()
.select()
.from(User.class)
.where(USER.AGE.between(18, 65)
.and(USER.CITY.in("New York", "London", "Tokyo"))
.or(USER.VIP_LEVEL.ge(5)));Advanced Query Features:
// Joins
QueryWrapper query = QueryWrapper.create()
.select(USER.NAME, ORDER.TOTAL)
.from(User.class)
.leftJoin(Order.class).on(USER.ID.eq(ORDER.USER_ID))
.where(ORDER.STATUS.eq("COMPLETED"));
// Grouping and aggregation
QueryWrapper query = QueryWrapper.create()
.select(USER.CITY, count(USER.ID).as("user_count"))
.from(User.class)
.where(USER.ACTIVE.eq(true))
.groupBy(USER.CITY)
.having(count(USER.ID).ge(10))
.orderBy(count(USER.ID).desc());
// Subqueries
QueryWrapper subQuery = QueryWrapper.create()
.select(ORDER.USER_ID)
.from(Order.class)
.where(ORDER.TOTAL.ge(1000));
QueryWrapper query = QueryWrapper.create()
.select()
.from(User.class)
.where(USER.ID.in(subQuery));Represents database columns with type-safe operations and SQL function support.
/**
* Represents a database column with type-safe operations
*/
public class QueryColumn {
/**
* Create column reference
* @param columnName database column name
* @return QueryColumn instance
*/
public static QueryColumn create(String columnName);
/**
* Create column reference with table alias
* @param columnName database column name
* @param tableAlias table alias
* @return QueryColumn instance
*/
public static QueryColumn create(String columnName, String tableAlias);
/**
* Add column alias
* @param alias column alias
* @return QueryColumn with alias
*/
public QueryColumn as(String alias);
// Comparison operations
/**
* Equal condition
* @param value comparison value
* @return QueryCondition
*/
public QueryCondition eq(Object value);
/**
* Not equal condition
* @param value comparison value
* @return QueryCondition
*/
public QueryCondition ne(Object value);
/**
* Greater than condition
* @param value comparison value
* @return QueryCondition
*/
public QueryCondition gt(Object value);
/**
* Greater than or equal condition
* @param value comparison value
* @return QueryCondition
*/
public QueryCondition ge(Object value);
/**
* Less than condition
* @param value comparison value
* @return QueryCondition
*/
public QueryCondition lt(Object value);
/**
* Less than or equal condition
* @param value comparison value
* @return QueryCondition
*/
public QueryCondition le(Object value);
/**
* IN condition
* @param values array of values
* @return QueryCondition
*/
public QueryCondition in(Object... values);
/**
* NOT IN condition
* @param values array of values
* @return QueryCondition
*/
public QueryCondition notIn(Object... values);
/**
* BETWEEN condition
* @param start start value
* @param end end value
* @return QueryCondition
*/
public QueryCondition between(Object start, Object end);
/**
* LIKE condition
* @param pattern like pattern
* @return QueryCondition
*/
public QueryCondition like(String pattern);
/**
* IS NULL condition
* @return QueryCondition
*/
public QueryCondition isNull();
/**
* IS NOT NULL condition
* @return QueryCondition
*/
public QueryCondition isNotNull();
// SQL functions
/**
* COUNT function
* @return QueryColumn with COUNT
*/
public QueryColumn count();
/**
* SUM function
* @return QueryColumn with SUM
*/
public QueryColumn sum();
/**
* AVG function
* @return QueryColumn with AVG
*/
public QueryColumn avg();
/**
* MAX function
* @return QueryColumn with MAX
*/
public QueryColumn max();
/**
* MIN function
* @return QueryColumn with MIN
*/
public QueryColumn min();
}Column Operations Examples:
// Basic comparisons
QueryCondition condition1 = USER.AGE.ge(18);
QueryCondition condition2 = USER.NAME.like("A%");
QueryCondition condition3 = USER.EMAIL.isNotNull();
// IN conditions
QueryCondition condition4 = USER.CITY.in("New York", "London", "Tokyo");
QueryCondition condition5 = USER.STATUS.notIn("DELETED", "SUSPENDED");
// BETWEEN conditions
QueryCondition condition6 = USER.CREATE_TIME.between(startDate, endDate);
QueryCondition condition7 = USER.SALARY.between(50000, 100000);
// SQL functions
QueryColumn userCount = USER.ID.count().as("total_users");
QueryColumn avgAge = USER.AGE.avg().as("average_age");
QueryColumn maxSalary = USER.SALARY.max().as("max_salary");Represents WHERE clause conditions with logical operators for combining multiple conditions.
/**
* Represents query conditions with logical operations
*/
public class QueryCondition {
/**
* Combine with AND logic
* @param condition condition to combine
* @return combined QueryCondition
*/
public QueryCondition and(QueryCondition condition);
/**
* Combine with OR logic
* @param condition condition to combine
* @return combined QueryCondition
*/
public QueryCondition or(QueryCondition condition);
/**
* Negate condition with NOT
* @return negated QueryCondition
*/
public QueryCondition not();
}Condition Combining Examples:
// Complex condition building
QueryCondition complexCondition = USER.AGE.ge(18)
.and(USER.ACTIVE.eq(true))
.and(USER.CITY.in("New York", "London")
.or(USER.VIP_LEVEL.ge(5)));
// Negation
QueryCondition notCondition = USER.STATUS.eq("DELETED").not();
// Grouped conditions
QueryCondition grouped = USER.AGE.between(25, 35)
.and(USER.SALARY.ge(60000)
.or(USER.EDUCATION.eq("PhD")));Static utility methods for common query operations and SQL functions.
/**
* Static utility methods for query building
*/
public class QueryMethods {
/**
* SELECT all columns
* @return QueryColumn array for all columns
*/
public static QueryColumn[] selectAll();
/**
* COUNT function
* @param column column to count
* @return QueryColumn with COUNT
*/
public static QueryColumn count(QueryColumn column);
/**
* COUNT(*) function
* @return QueryColumn with COUNT(*)
*/
public static QueryColumn count();
/**
* DISTINCT function
* @param column column for distinct
* @return QueryColumn with DISTINCT
*/
public static QueryColumn distinct(QueryColumn column);
/**
* SUM function
* @param column column to sum
* @return QueryColumn with SUM
*/
public static QueryColumn sum(QueryColumn column);
/**
* AVG function
* @param column column to average
* @return QueryColumn with AVG
*/
public static QueryColumn avg(QueryColumn column);
/**
* MAX function
* @param column column to find maximum
* @return QueryColumn with MAX
*/
public static QueryColumn max(QueryColumn column);
/**
* MIN function
* @param column column to find minimum
* @return QueryColumn with MIN
*/
public static QueryColumn min(QueryColumn column);
}Static Method Examples:
import static com.mybatisflex.core.query.QueryMethods.*;
// Using static methods
QueryWrapper query = QueryWrapper.create()
.select(count(), avg(USER.AGE), max(USER.SALARY))
.from(User.class)
.where(USER.ACTIVE.eq(true));
// Distinct queries
QueryWrapper distinctQuery = QueryWrapper.create()
.select(distinct(USER.CITY))
.from(User.class);Type-safe column references using lambda expressions for compile-time checking.
/**
* Lambda getter interface for type-safe column references
* @param <T> entity type
*/
public interface LambdaGetter<T> extends Serializable, Function<T, Object> {
// Marker interface for lambda getters
}Lambda Examples:
// Type-safe column selection with lambdas
QueryWrapper lambdaQuery = QueryWrapper.create()
.select(User::getName, User::getEmail, User::getAge)
.from(User.class)
.where(USER.ACTIVE.eq(true));
// Lambda conditions (if supported by entity fields)
QueryWrapper conditionQuery = QueryWrapper.create()
.select()
.from(User.class)
.where(USER.AGE.ge(18));// Core query types
public class QueryTable {
public static QueryTable create(String tableName);
public static QueryTable create(Class<?> entityClass);
public QueryTable as(String alias);
}
// Order by support
public class QueryOrderBy {
public static QueryOrderBy asc(QueryColumn column);
public static QueryOrderBy desc(QueryColumn column);
}
// Join conditions
public class JoinCondition {
public JoinCondition on(QueryCondition condition);
public JoinCondition and(QueryCondition condition);
public JoinCondition or(QueryCondition condition);
}
// Functional interfaces
@FunctionalInterface
public interface LambdaGetter<T> extends Serializable, Function<T, Object> {
}Install with Tessl CLI
npx tessl i tessl/maven-com-mybatis-flex--mybatis-flex-core