MyBatis-Flex is an elegant enhancement framework for MyBatis providing type-safe query building, active record patterns, and comprehensive ORM capabilities
—
Comprehensive CRUD interface that eliminates the need for custom mapper methods. The BaseMapper interface provides all standard database operations with support for batch processing, relationship loading, and advanced querying.
Universal CRUD interface that all entity mappers should extend. Provides complete database operations without requiring custom method definitions.
/**
* Universal CRUD interface for all entity operations
* @param <T> Entity type
*/
public interface BaseMapper<T> {
// Insert operations
int insert(T entity);
int insert(T entity, boolean ignoreNulls);
int insertSelective(T entity);
int insertWithPk(T entity);
int insertSelectiveWithPk(T entity);
int insertWithPk(T entity, boolean ignoreNulls);
int insertBatch(Collection<T> entities);
int insertBatch(Collection<T> entities, int size);
int insertBatchSelective(Collection<T> entities);
int insertBatchSelective(Collection<T> entities, int size);
int insertOrUpdate(T entity);
int insertOrUpdateSelective(T entity);
int insertOrUpdate(T entity, boolean ignoreNulls);
// Select operations
T selectOneByEntityId(T entity);
T selectOneById(Serializable id);
T selectOneByMap(Map<String, Object> whereConditions);
T selectOneByCondition(QueryCondition whereConditions);
T selectOneByQuery(QueryWrapper queryWrapper);
<R> R selectOneByQueryAs(QueryWrapper queryWrapper, Class<R> asType);
T selectOneWithRelationsByMap(Map<String, Object> whereConditions);
T selectOneWithRelationsByCondition(QueryCondition whereConditions);
T selectOneWithRelationsByQuery(QueryWrapper queryWrapper);
T selectOneWithRelationsById(Serializable id);
<R> R selectOneWithRelationsByIdAs(Serializable id, Class<R> asType);
<R> R selectOneWithRelationsByQueryAs(QueryWrapper queryWrapper, Class<R> asType);
List<T> selectListByIds(Collection<? extends Serializable> ids);
List<T> selectListByMap(Map<String, Object> whereConditions);
List<T> selectListByMap(Map<String, Object> whereConditions, Long count);
List<T> selectListByCondition(QueryCondition whereConditions);
List<T> selectListByCondition(QueryCondition whereConditions, Long count);
List<T> selectListByQuery(QueryWrapper queryWrapper);
List<T> selectListByQuery(QueryWrapper queryWrapper, Consumer<FieldQueryBuilder<T>>... consumers);
Cursor<T> selectCursorByQuery(QueryWrapper queryWrapper);
<R> Cursor<R> selectCursorByQueryAs(QueryWrapper queryWrapper, Class<R> asType);
List<Row> selectRowsByQuery(QueryWrapper queryWrapper);
<R> List<R> selectListByQueryAs(QueryWrapper queryWrapper, Class<R> asType);
<R> List<R> selectListByQueryAs(QueryWrapper queryWrapper, Class<R> asType, Consumer<FieldQueryBuilder<R>>... consumers);
List<T> selectListWithRelationsByQuery(QueryWrapper queryWrapper);
<R> List<R> selectListWithRelationsByQueryAs(QueryWrapper queryWrapper, Class<R> asType);
<R> List<R> selectListWithRelationsByQueryAs(QueryWrapper queryWrapper, Class<R> asType, Consumer<FieldQueryBuilder<R>>... consumers);
List<T> selectAll();
List<T> selectAllWithRelations();
Object selectObjectByQuery(QueryWrapper queryWrapper);
<R> R selectObjectByQueryAs(QueryWrapper queryWrapper, Class<R> asType);
List<Object> selectObjectListByQuery(QueryWrapper queryWrapper);
<R> List<R> selectObjectListByQueryAs(QueryWrapper queryWrapper, Class<R> asType);
long selectCountByQuery(QueryWrapper queryWrapper);
long selectCountByCondition(QueryCondition whereConditions);
// Update operations
int update(T entity);
int update(T entity, boolean ignoreNulls);
int updateByMap(T entity, Map<String, Object> whereConditions);
int updateByMap(T entity, boolean ignoreNulls, Map<String, Object> whereConditions);
int updateByCondition(T entity, QueryCondition whereConditions);
int updateByCondition(T entity, boolean ignoreNulls, QueryCondition whereConditions);
int updateByQuery(T entity, QueryWrapper queryWrapper);
int updateByQuery(T entity, boolean ignoreNulls, QueryWrapper queryWrapper);
// Delete operations
int delete(T entity);
int deleteById(Serializable id);
int deleteBatchByIds(Collection<? extends Serializable> ids);
int deleteBatchByIds(Collection<? extends Serializable> ids, int size);
int deleteByMap(Map<String, Object> whereConditions);
int deleteByCondition(QueryCondition whereConditions);
int deleteByQuery(QueryWrapper queryWrapper);
// Pagination operations
Page<T> paginate(Number pageNumber, Number pageSize, QueryWrapper queryWrapper);
Page<T> paginateWithRelations(Number pageNumber, Number pageSize, QueryWrapper queryWrapper);
Page<T> paginate(Number pageNumber, Number pageSize, QueryCondition whereConditions);
Page<T> paginateWithRelations(Number pageNumber, Number pageSize, QueryCondition whereConditions);
Page<T> paginate(Number pageNumber, Number pageSize, Number totalRow, QueryWrapper queryWrapper);
Page<T> paginateWithRelations(Number pageNumber, Number pageSize, Number totalRow, QueryWrapper queryWrapper);
Page<T> paginate(Number pageNumber, Number pageSize, Number totalRow, QueryCondition whereConditions);
Page<T> paginateWithRelations(Number pageNumber, Number pageSize, Number totalRow, QueryCondition whereConditions);
Page<T> paginate(Page<T> page, QueryWrapper queryWrapper);
Page<T> paginate(Page<T> page, QueryWrapper queryWrapper, Consumer<FieldQueryBuilder<T>>... consumers);
Page<T> paginateWithRelations(Page<T> page, QueryWrapper queryWrapper);
Page<T> paginateWithRelations(Page<T> page, QueryWrapper queryWrapper, Consumer<FieldQueryBuilder<T>>... consumers);
<R> Page<R> paginateAs(Number pageNumber, Number pageSize, QueryWrapper queryWrapper, Class<R> asType);
<R> Page<R> paginateAs(Number pageNumber, Number pageSize, Number totalRow, QueryWrapper queryWrapper, Class<R> asType);
<R> Page<R> paginateAs(Page<R> page, QueryWrapper queryWrapper, Class<R> asType);
<R> Page<R> paginateAs(Page<R> page, QueryWrapper queryWrapper, Class<R> asType, Consumer<FieldQueryBuilder<R>>... consumers);
<R> Page<R> paginateWithRelationsAs(Number pageNumber, Number pageSize, QueryWrapper queryWrapper, Class<R> asType);
<R> Page<R> paginateWithRelationsAs(Number pageNumber, Number pageSize, Number totalRow, QueryWrapper queryWrapper, Class<R> asType);
<R> Page<R> paginateWithRelationsAs(Page<R> page, QueryWrapper queryWrapper, Class<R> asType);
<R> Page<R> paginateWithRelationsAs(Page<R> page, QueryWrapper queryWrapper, Class<R> asType, Consumer<FieldQueryBuilder<R>>... consumers);
// XML operations
<E> Page<E> xmlPaginate(String dataSelectId, Page<E> page, QueryWrapper queryWrapper);
<E> Page<E> xmlPaginate(String dataSelectId, Page<E> page, Map<String, Object> otherParams);
<E> Page<E> xmlPaginate(String dataSelectId, Page<E> page, QueryWrapper queryWrapper, Map<String, Object> otherParams);
<E> Page<E> xmlPaginate(String dataSelectId, String countSelectId, Page<E> page, QueryWrapper queryWrapper, Map<String, Object> otherParams);
}Basic Mapper Definition:
import com.mybatisflex.core.BaseMapper;
// Entity class
@Table("users")
public class User {
@Id
private Long id;
private String name;
private Integer age;
private String email;
// constructors, getters, setters...
}
// Mapper interface - no custom methods needed!
public interface UserMapper extends BaseMapper<User> {
// Inherits all CRUD operations from BaseMapper
}Comprehensive insert capabilities including selective insertion, batch operations, and upsert functionality.
/**
* Insert entity with all fields (including null values)
* @param entity entity to insert
* @return number of affected rows
*/
int insert(T entity);
/**
* Insert entity with control over null value handling
* @param entity entity to insert
* @param ignoreNulls whether to ignore null values
* @return number of affected rows
*/
int insert(T entity, boolean ignoreNulls);
/**
* Insert entity ignoring null fields (selective insert)
* Allows database default values to take effect for null fields
* @param entity entity to insert
* @return number of affected rows
*/
int insertSelective(T entity);
/**
* Insert entity with primary key value (bypasses primary key generator)
* @param entity entity to insert with pre-set primary key
* @return number of affected rows
*/
int insertWithPk(T entity);
/**
* Insert entity with primary key value, ignoring null fields
* @param entity entity to insert with pre-set primary key
* @return number of affected rows
*/
int insertSelectiveWithPk(T entity);
/**
* Insert entity with primary key value and null handling control
* @param entity entity to insert with pre-set primary key
* @param ignoreNulls whether to ignore null values
* @return number of affected rows
*/
int insertWithPk(T entity, boolean ignoreNulls);
/**
* Batch insert multiple entities (based on first entity's field structure)
* @param entities collection of entities to insert
* @return number of affected rows
*/
int insertBatch(Collection<T> entities);
/**
* Batch insert multiple entities with size chunking
* @param entities collection of entities to insert
* @param size chunk size for batching (0 or negative uses default size)
* @return number of affected rows
*/
int insertBatch(Collection<T> entities, int size);
/**
* Batch insert multiple entities ignoring null values
* Uses selective insertion strategy for each entity
* @param entities collection of entities to insert
* @return number of affected rows
*/
int insertBatchSelective(Collection<T> entities);
/**
* Batch insert multiple entities ignoring null values with size chunking
* @param entities collection of entities to insert
* @param size chunk size for batching (0 or negative uses default size)
* @return number of affected rows
*/
int insertBatchSelective(Collection<T> entities, int size);
/**
* Insert or update entity (upsert operation)
* Updates if primary key exists, inserts if not
* @param entity entity to insert or update
* @return number of affected rows
*/
int insertOrUpdate(T entity);
/**
* Insert or update entity with selective null handling (upsert operation)
* Updates if primary key exists, inserts if not, ignoring null fields
* @param entity entity to insert or update
* @return number of affected rows
*/
int insertOrUpdateSelective(T entity);
/**
* Insert or update entity with null handling control (upsert operation)
* @param entity entity to insert or update
* @param ignoreNulls whether to ignore null values
* @return number of affected rows
*/
int insertOrUpdate(T entity, boolean ignoreNulls);Insert Examples:
UserMapper userMapper = // ... get mapper instance
// Basic insert (includes null values)
User user = new User("Alice", 25, "alice@example.com");
int rows = userMapper.insert(user);
// Insert with null control
User userWithNulls = new User("Bob", null, "bob@example.com");
userMapper.insert(userWithNulls, false); // Include nulls
userMapper.insert(userWithNulls, true); // Ignore nulls
// Selective insert (ignores null fields)
User partialUser = new User();
partialUser.setName("Charlie");
partialUser.setAge(30);
// email remains null and won't be inserted
userMapper.insertSelective(partialUser);
// Insert with primary key (bypasses PK generator)
User userWithId = new User();
userWithId.setId(100L);
userWithId.setName("Diana");
userWithId.setAge(28);
userMapper.insertWithPk(userWithId);
// Insert with PK, ignoring nulls
userMapper.insertSelectiveWithPk(userWithId);
// Batch insert
List<User> users = Arrays.asList(
new User("Eve", 28, "eve@example.com"),
new User("Frank", 32, "frank@example.com")
);
userMapper.insertBatch(users);
// Batch insert with chunking
List<User> manyUsers = generateManyUsers();
userMapper.insertBatch(manyUsers, 500); // Insert in chunks of 500
// Batch selective insert (ignores nulls for all entities)
List<User> usersWithNulls = generateUsersWithNulls();
userMapper.insertBatchSelective(usersWithNulls);
// Upsert operations
User existingUser = new User();
existingUser.setId(1L);
existingUser.setName("Alice Updated");
existingUser.setAge(26);
userMapper.insertOrUpdate(existingUser); // Updates if ID exists, inserts if not
// Selective upsert (ignores nulls)
userMapper.insertOrUpdateSelective(existingUser);
// Upsert with null control
userMapper.insertOrUpdate(existingUser, true); // Ignore nullsComprehensive query operations including single record retrieval, list queries, counting, and relationship loading.
/**
* Select single entity by entity's primary key values
* @param entity entity containing primary key values
* @return entity or null if not found
*/
T selectOneByEntityId(T entity);
/**
* Select single entity by primary key
* @param id primary key value
* @return entity or null if not found
*/
T selectOneById(Serializable id);
/**
* Select single entity by Map conditions
* @param whereConditions key-value condition pairs
* @return entity or null if not found
*/
T selectOneByMap(Map<String, Object> whereConditions);
/**
* Select single entity by QueryCondition
* @param whereConditions query conditions
* @return entity or null if not found
*/
T selectOneByCondition(QueryCondition whereConditions);
/**
* Select single entity by query conditions
* @param queryWrapper query conditions
* @return single entity or null
*/
T selectOneByQuery(QueryWrapper queryWrapper);
/**
* Select single entity by query conditions with type conversion
* @param queryWrapper query conditions
* @param asType target type for conversion
* @return converted entity or null
*/
<R> R selectOneByQueryAs(QueryWrapper queryWrapper, Class<R> asType);
/**
* Select single entity with relationships by Map conditions
* @param whereConditions key-value condition pairs
* @return entity with relationships or null
*/
T selectOneWithRelationsByMap(Map<String, Object> whereConditions);
/**
* Select single entity with relationships by QueryCondition
* @param whereConditions query conditions
* @return entity with relationships or null
*/
T selectOneWithRelationsByCondition(QueryCondition whereConditions);
/**
* Select single entity with relationships loaded
* @param queryWrapper query conditions
* @return entity with relationships
*/
T selectOneWithRelationsByQuery(QueryWrapper queryWrapper);
/**
* Select single entity with relationships by primary key
* @param id primary key value
* @return entity with relationships or null
*/
T selectOneWithRelationsById(Serializable id);
/**
* Select single entity with relationships by primary key with type conversion
* @param id primary key value
* @param asType target type for conversion
* @return converted entity with relationships or null
*/
<R> R selectOneWithRelationsByIdAs(Serializable id, Class<R> asType);
/**
* Select single entity with relationships by query with type conversion
* @param queryWrapper query conditions
* @param asType target type for conversion
* @return converted entity with relationships or null
*/
<R> R selectOneWithRelationsByQueryAs(QueryWrapper queryWrapper, Class<R> asType);
/**
* Select multiple entities by primary keys
* @param ids collection of primary key values
* @return list of entities
*/
List<T> selectListByIds(Collection<? extends Serializable> ids);
/**
* Select entities by Map conditions
* @param whereConditions key-value condition pairs
* @return list of entities
*/
List<T> selectListByMap(Map<String, Object> whereConditions);
/**
* Select limited entities by Map conditions
* @param whereConditions key-value condition pairs
* @param count maximum number of records to return
* @return list of entities
*/
List<T> selectListByMap(Map<String, Object> whereConditions, Long count);
/**
* Select entities by QueryCondition
* @param whereConditions query conditions
* @return list of entities
*/
List<T> selectListByCondition(QueryCondition whereConditions);
/**
* Select limited entities by QueryCondition
* @param whereConditions query conditions
* @param count maximum number of records to return
* @return list of entities
*/
List<T> selectListByCondition(QueryCondition whereConditions, Long count);
/**
* Select entities by query conditions
* @param queryWrapper query conditions
* @return list of entities
*/
List<T> selectListByQuery(QueryWrapper queryWrapper);
/**
* Select entities by query conditions with field loading
* @param queryWrapper query conditions
* @param consumers field loading specifications
* @return list of entities
*/
List<T> selectListByQuery(QueryWrapper queryWrapper, Consumer<FieldQueryBuilder<T>>... consumers);
/**
* Select entities as cursor (requires transaction)
* @param queryWrapper query conditions
* @return cursor for streaming results
*/
Cursor<T> selectCursorByQuery(QueryWrapper queryWrapper);
/**
* Select entities as cursor with type conversion (requires transaction)
* @param queryWrapper query conditions
* @param asType target type for conversion
* @return cursor for streaming results
*/
<R> Cursor<R> selectCursorByQueryAs(QueryWrapper queryWrapper, Class<R> asType);
/**
* Select entities as Row objects (Map-like structure)
* @param queryWrapper query conditions
* @return list of Row objects
*/
List<Row> selectRowsByQuery(QueryWrapper queryWrapper);
/**
* Select entities by query conditions with type conversion
* @param queryWrapper query conditions
* @param asType target type for conversion
* @return list of converted entities
*/
<R> List<R> selectListByQueryAs(QueryWrapper queryWrapper, Class<R> asType);
/**
* Select entities with type conversion and field loading
* @param queryWrapper query conditions
* @param asType target type for conversion
* @param consumers field loading specifications
* @return list of converted entities
*/
<R> List<R> selectListByQueryAs(QueryWrapper queryWrapper, Class<R> asType, Consumer<FieldQueryBuilder<R>>... consumers);
/**
* Select entities with relationships loaded
* @param queryWrapper query conditions
* @return list of entities with relationships
*/
List<T> selectListWithRelationsByQuery(QueryWrapper queryWrapper);
/**
* Select entities with relationships and type conversion
* @param queryWrapper query conditions
* @param asType target type for conversion
* @return list of converted entities with relationships
*/
<R> List<R> selectListWithRelationsByQueryAs(QueryWrapper queryWrapper, Class<R> asType);
/**
* Select entities with relationships, type conversion, and field loading
* @param queryWrapper query conditions
* @param asType target type for conversion
* @param consumers field loading specifications
* @return list of converted entities with relationships
*/
<R> List<R> selectListWithRelationsByQueryAs(QueryWrapper queryWrapper, Class<R> asType, Consumer<FieldQueryBuilder<R>>... consumers);
/**
* Select all entities from table
* @return list of all entities
*/
List<T> selectAll();
/**
* Select all entities with relationships loaded
* @return list of all entities with relationships
*/
List<T> selectAllWithRelations();
/**
* Select single object value from first column of query result
* @param queryWrapper query conditions (should select single column)
* @return object value or null
*/
Object selectObjectByQuery(QueryWrapper queryWrapper);
/**
* Select single object value with type conversion
* @param queryWrapper query conditions (should select single column)
* @param asType target type for conversion
* @return converted object value or null
*/
<R> R selectObjectByQueryAs(QueryWrapper queryWrapper, Class<R> asType);
/**
* Select list of object values from first column of query result
* @param queryWrapper query conditions (should select single column)
* @return list of object values
*/
List<Object> selectObjectListByQuery(QueryWrapper queryWrapper);
/**
* Select list of object values with type conversion
* @param queryWrapper query conditions (should select single column)
* @param asType target type for conversion
* @return list of converted object values
*/
<R> List<R> selectObjectListByQueryAs(QueryWrapper queryWrapper, Class<R> asType);
/**
* Count entities matching query conditions
* @param queryWrapper query conditions
* @return count of matching entities
*/
long selectCountByQuery(QueryWrapper queryWrapper);
/**
* Count entities matching QueryCondition
* @param whereConditions query conditions
* @return count of matching entities
*/
long selectCountByCondition(QueryCondition whereConditions);Select Examples:
// Select by primary key
User user = userMapper.selectOneById(1L);
// Select by entity's primary key
User searchUser = new User();
searchUser.setId(1L);
User foundUser = userMapper.selectOneByEntityId(searchUser);
// Select by Map conditions
Map<String, Object> conditions = Map.of("age", 25, "status", "ACTIVE");
User userByMap = userMapper.selectOneByMap(conditions);
// Select by QueryCondition
User userByCondition = userMapper.selectOneByCondition(USER.AGE.eq(25));
// Select multiple by IDs
List<Long> ids = Arrays.asList(1L, 2L, 3L);
List<User> users = userMapper.selectListByIds(ids);
// Select with QueryWrapper
List<User> adults = userMapper.selectListByQuery(
QueryWrapper.create()
.select()
.from(User.class)
.where(USER.AGE.ge(18))
.orderBy(USER.NAME.asc())
);
// Select with limited count by Map
List<User> limitedUsers = userMapper.selectListByMap(
Map.of("status", "ACTIVE"), 10L
);
// Select with type conversion
List<UserDto> userDtos = userMapper.selectListByQueryAs(
QueryWrapper.create()
.select(USER.ID, USER.NAME, USER.AGE)
.from(User.class),
UserDto.class
);
// Select as cursor (streaming, requires transaction)
try (Cursor<User> cursor = userMapper.selectCursorByQuery(
QueryWrapper.create().from(User.class)
)) {
for (User u : cursor) {
// Process one by one
}
}
// Select as Row objects (Map-like)
List<Row> rows = userMapper.selectRowsByQuery(
QueryWrapper.create()
.select(USER.NAME, USER.AGE)
.from(User.class)
);
// Select all entities
List<User> allUsers = userMapper.selectAll();
// Select all with relationships
List<User> allUsersWithRelations = userMapper.selectAllWithRelations();
// Select single object (for aggregate functions)
Long maxAge = userMapper.selectObjectByQueryAs(
QueryWrapper.create()
.select(USER.AGE.max())
.from(User.class),
Long.class
);
// Select object list (for single column results)
List<String> names = userMapper.selectObjectListByQueryAs(
QueryWrapper.create()
.select(USER.NAME)
.from(User.class),
String.class
);
// Count records
long adultCount = userMapper.selectCountByQuery(
QueryWrapper.create()
.from(User.class)
.where(USER.AGE.ge(18))
);
// Count by condition
long activeCount = userMapper.selectCountByCondition(USER.STATUS.eq("ACTIVE"));
// Select with relationships
User userWithRelations = userMapper.selectOneWithRelationsById(1L);
// Select with relationships and type conversion
UserDto userDtoWithRelations = userMapper.selectOneWithRelationsByIdAs(1L, UserDto.class);
// Select with field loading
List<User> usersWithFields = userMapper.selectListByQuery(
QueryWrapper.create().from(User.class),
fieldQuery -> fieldQuery.load(USER.ORDERS)
);Flexible update operations supporting full updates, selective updates, and condition-based updates.
/**
* Update entity by primary key (ignores null fields by default)
* @param entity entity with updated values and primary key
* @return number of affected rows
*/
int update(T entity);
/**
* Update entity by primary key with null handling control
* @param entity entity with updated values and primary key
* @param ignoreNulls whether to ignore null fields
* @return number of affected rows
*/
int update(T entity, boolean ignoreNulls);
/**
* Update entity by Map conditions
* @param entity entity with updated values
* @param whereConditions key-value condition pairs
* @return number of affected rows
*/
int updateByMap(T entity, Map<String, Object> whereConditions);
/**
* Update entity by Map conditions with null handling control
* @param entity entity with updated values
* @param ignoreNulls whether to ignore null fields
* @param whereConditions key-value condition pairs
* @return number of affected rows
*/
int updateByMap(T entity, boolean ignoreNulls, Map<String, Object> whereConditions);
/**
* Update entity by QueryCondition
* @param entity entity with updated values
* @param whereConditions query conditions
* @return number of affected rows
*/
int updateByCondition(T entity, QueryCondition whereConditions);
/**
* Update entity by QueryCondition with null handling control
* @param entity entity with updated values
* @param ignoreNulls whether to ignore null fields
* @param whereConditions query conditions
* @return number of affected rows
*/
int updateByCondition(T entity, boolean ignoreNulls, QueryCondition whereConditions);
/**
* Update entities matching query conditions (ignores nulls by default)
* @param entity entity with updated values
* @param queryWrapper conditions for which records to update
* @return number of affected rows
*/
int updateByQuery(T entity, QueryWrapper queryWrapper);
/**
* Update entities matching query conditions with null handling control
* @param entity entity with updated values
* @param ignoreNulls whether to ignore null fields
* @param queryWrapper conditions for which records to update
* @return number of affected rows
*/
int updateByQuery(T entity, boolean ignoreNulls, QueryWrapper queryWrapper);Update Examples:
// Update by primary key (ignores nulls by default)
User user = userMapper.selectOneById(1L);
user.setAge(26);
user.setEmail("alice.updated@example.com");
userMapper.update(user);
// Update with null control
User userWithNulls = new User();
userWithNulls.setId(1L);
userWithNulls.setAge(27);
userWithNulls.setEmail(null); // Will be ignored
userMapper.update(userWithNulls, true); // Ignore nulls
userWithNulls.setEmail(null);
userMapper.update(userWithNulls, false); // Include nulls (sets email to NULL)
// Update by Map conditions
User updates = new User();
updates.setStatus("INACTIVE");
updates.setUpdatedAt(LocalDateTime.now());
Map<String, Object> conditions = Map.of("age", 25);
userMapper.updateByMap(updates, conditions);
// Update by Map conditions with null control
userMapper.updateByMap(updates, true, conditions); // Ignore nulls
// Update by QueryCondition
userMapper.updateByCondition(updates, USER.AGE.lt(18));
// Update by QueryCondition with null control
userMapper.updateByCondition(updates, false, USER.AGE.lt(18)); // Include nulls
// Update by QueryWrapper (ignores nulls by default)
User statusUpdate = new User();
statusUpdate.setStatus("VERIFIED");
userMapper.updateByQuery(statusUpdate,
QueryWrapper.create()
.from(User.class)
.where(USER.EMAIL.isNotNull())
.and(USER.STATUS.eq("PENDING"))
);
// Update by QueryWrapper with null control
User nullUpdate = new User();
nullUpdate.setLastLoginTime(null); // Will set to NULL
userMapper.updateByQuery(nullUpdate, false,
QueryWrapper.create()
.from(User.class)
.where(USER.STATUS.eq("INACTIVE"))
);Comprehensive delete operations supporting single deletion, batch deletion, and condition-based deletion.
/**
* Delete entity by entity's primary key values
* @param entity entity containing primary key values
* @return number of affected rows
*/
int delete(T entity);
/**
* Delete entity by primary key
* @param id primary key value
* @return number of affected rows
*/
int deleteById(Serializable id);
/**
* Delete multiple entities by primary keys
* @param ids collection of primary key values
* @return number of affected rows
*/
int deleteBatchByIds(Collection<? extends Serializable> ids);
/**
* Delete multiple entities by primary keys with size chunking
* @param ids collection of primary key values
* @param size chunk size for batching (0 or negative uses default size)
* @return number of affected rows
*/
int deleteBatchByIds(Collection<? extends Serializable> ids, int size);
/**
* Delete entities by Map conditions
* @param whereConditions key-value condition pairs
* @return number of affected rows
*/
int deleteByMap(Map<String, Object> whereConditions);
/**
* Delete entities by QueryCondition
* @param whereConditions query conditions
* @return number of affected rows
*/
int deleteByCondition(QueryCondition whereConditions);
/**
* Delete entities matching query conditions
* @param queryWrapper conditions for which records to delete
* @return number of affected rows
*/
int deleteByQuery(QueryWrapper queryWrapper);Delete Examples:
// Delete by entity's primary key
User userToDelete = new User();
userToDelete.setId(1L);
int deleted = userMapper.delete(userToDelete);
// Delete by primary key
int deletedById = userMapper.deleteById(1L);
// Batch delete by IDs
List<Long> idsToDelete = Arrays.asList(2L, 3L, 4L);
int batchDeleted = userMapper.deleteBatchByIds(idsToDelete);
// Batch delete with chunking
List<Long> manyIds = generateManyIds();
int chunkedDeleted = userMapper.deleteBatchByIds(manyIds, 500); // Delete in chunks of 500
// Delete by Map conditions
Map<String, Object> conditions = Map.of("status", "INACTIVE", "age", 0);
int deletedByMap = userMapper.deleteByMap(conditions);
// Delete by QueryCondition
int deletedByCondition = userMapper.deleteByCondition(USER.STATUS.eq("DELETED"));
// Delete by QueryWrapper
int conditionalDeleted = userMapper.deleteByQuery(
QueryWrapper.create()
.from(User.class)
.where(USER.AGE.lt(18))
.and(USER.STATUS.eq("INACTIVE"))
);
// Complex conditional delete
int complexDelete = userMapper.deleteByQuery(
QueryWrapper.create()
.from(User.class)
.where(USER.CREATED_AT.lt(LocalDateTime.now().minusYears(1)))
.and(USER.LAST_LOGIN_TIME.isNull())
);Built-in pagination support with count optimization, type conversion, and relationship loading.
/**
* Paginate query results with page number and size
* @param pageNumber current page number (1-based)
* @param pageSize number of records per page
* @param queryWrapper query conditions
* @return page of results with total count
*/
Page<T> paginate(Number pageNumber, Number pageSize, QueryWrapper queryWrapper);
/**
* Paginate query results with relationships loaded
* @param pageNumber current page number (1-based)
* @param pageSize number of records per page
* @param queryWrapper query conditions
* @return page of results with relationships and total count
*/
Page<T> paginateWithRelations(Number pageNumber, Number pageSize, QueryWrapper queryWrapper);
/**
* Paginate query results by QueryCondition
* @param pageNumber current page number (1-based)
* @param pageSize number of records per page
* @param whereConditions query conditions
* @return page of results with total count
*/
Page<T> paginate(Number pageNumber, Number pageSize, QueryCondition whereConditions);
/**
* Paginate query results by QueryCondition with relationships
* @param pageNumber current page number (1-based)
* @param pageSize number of records per page
* @param whereConditions query conditions
* @return page of results with relationships and total count
*/
Page<T> paginateWithRelations(Number pageNumber, Number pageSize, QueryCondition whereConditions);
/**
* Paginate query results with known total row count
* @param pageNumber current page number (1-based)
* @param pageSize number of records per page
* @param totalRow total number of records (skips count query)
* @param queryWrapper query conditions
* @return page of results
*/
Page<T> paginate(Number pageNumber, Number pageSize, Number totalRow, QueryWrapper queryWrapper);
/**
* Paginate query results with known total row count and relationships
* @param pageNumber current page number (1-based)
* @param pageSize number of records per page
* @param totalRow total number of records (skips count query)
* @param queryWrapper query conditions
* @return page of results with relationships
*/
Page<T> paginateWithRelations(Number pageNumber, Number pageSize, Number totalRow, QueryWrapper queryWrapper);
/**
* Paginate query results by QueryCondition with known total row count
* @param pageNumber current page number (1-based)
* @param pageSize number of records per page
* @param totalRow total number of records (skips count query)
* @param whereConditions query conditions
* @return page of results
*/
Page<T> paginate(Number pageNumber, Number pageSize, Number totalRow, QueryCondition whereConditions);
/**
* Paginate query results by QueryCondition with known total row count and relationships
* @param pageNumber current page number (1-based)
* @param pageSize number of records per page
* @param totalRow total number of records (skips count query)
* @param whereConditions query conditions
* @return page of results with relationships
*/
Page<T> paginateWithRelations(Number pageNumber, Number pageSize, Number totalRow, QueryCondition whereConditions);
/**
* Paginate query results using Page object
* @param page pagination parameters (page number, size, optional total count)
* @param queryWrapper query conditions
* @return page of results with total count
*/
Page<T> paginate(Page<T> page, QueryWrapper queryWrapper);
/**
* Paginate query results with field loading
* @param page pagination parameters
* @param queryWrapper query conditions
* @param consumers field loading specifications
* @return page of results with loaded fields
*/
Page<T> paginate(Page<T> page, QueryWrapper queryWrapper, Consumer<FieldQueryBuilder<T>>... consumers);
/**
* Paginate query results with relationships loaded
* @param page pagination parameters
* @param queryWrapper query conditions
* @return page of results with relationships
*/
Page<T> paginateWithRelations(Page<T> page, QueryWrapper queryWrapper);
/**
* Paginate query results with relationships and field loading
* @param page pagination parameters
* @param queryWrapper query conditions
* @param consumers field loading specifications
* @return page of results with relationships and loaded fields
*/
Page<T> paginateWithRelations(Page<T> page, QueryWrapper queryWrapper, Consumer<FieldQueryBuilder<T>>... consumers);
/**
* Paginate query results with type conversion
* @param pageNumber current page number (1-based)
* @param pageSize number of records per page
* @param queryWrapper query conditions
* @param asType target type for conversion
* @return page of converted results
*/
<R> Page<R> paginateAs(Number pageNumber, Number pageSize, QueryWrapper queryWrapper, Class<R> asType);
/**
* Paginate query results with type conversion and known total count
* @param pageNumber current page number (1-based)
* @param pageSize number of records per page
* @param totalRow total number of records
* @param queryWrapper query conditions
* @param asType target type for conversion
* @return page of converted results
*/
<R> Page<R> paginateAs(Number pageNumber, Number pageSize, Number totalRow, QueryWrapper queryWrapper, Class<R> asType);
/**
* Paginate query results with type conversion using Page object
* @param page pagination parameters
* @param queryWrapper query conditions
* @param asType target type for conversion
* @return page of converted results
*/
<R> Page<R> paginateAs(Page<R> page, QueryWrapper queryWrapper, Class<R> asType);
/**
* Paginate query results with type conversion and field loading
* @param page pagination parameters
* @param queryWrapper query conditions
* @param asType target type for conversion
* @param consumers field loading specifications
* @return page of converted results with loaded fields
*/
<R> Page<R> paginateAs(Page<R> page, QueryWrapper queryWrapper, Class<R> asType, Consumer<FieldQueryBuilder<R>>... consumers);
/**
* Paginate query results with relationships and type conversion
* @param pageNumber current page number (1-based)
* @param pageSize number of records per page
* @param queryWrapper query conditions
* @param asType target type for conversion
* @return page of converted results with relationships
*/
<R> Page<R> paginateWithRelationsAs(Number pageNumber, Number pageSize, QueryWrapper queryWrapper, Class<R> asType);
/**
* Paginate query results with relationships, type conversion, and known total count
* @param pageNumber current page number (1-based)
* @param pageSize number of records per page
* @param totalRow total number of records
* @param queryWrapper query conditions
* @param asType target type for conversion
* @return page of converted results with relationships
*/
<R> Page<R> paginateWithRelationsAs(Number pageNumber, Number pageSize, Number totalRow, QueryWrapper queryWrapper, Class<R> asType);
/**
* Paginate query results with relationships and type conversion using Page object
* @param page pagination parameters
* @param queryWrapper query conditions
* @param asType target type for conversion
* @return page of converted results with relationships
*/
<R> Page<R> paginateWithRelationsAs(Page<R> page, QueryWrapper queryWrapper, Class<R> asType);
/**
* Paginate query results with relationships, type conversion, and field loading
* @param page pagination parameters
* @param queryWrapper query conditions
* @param asType target type for conversion
* @param consumers field loading specifications
* @return page of converted results with relationships and loaded fields
*/
<R> Page<R> paginateWithRelationsAs(Page<R> page, QueryWrapper queryWrapper, Class<R> asType, Consumer<FieldQueryBuilder<R>>... consumers);Pagination Examples:
// Basic pagination with page number and size
Page<User> result1 = userMapper.paginate(1, 10,
QueryWrapper.create()
.select()
.from(User.class)
.where(USER.AGE.ge(18))
.orderBy(USER.NAME.asc())
);
// Pagination with relationships loaded
Page<User> resultWithRelations = userMapper.paginateWithRelations(1, 10,
QueryWrapper.create()
.from(User.class)
.where(USER.STATUS.eq("ACTIVE"))
);
// Pagination by QueryCondition
Page<User> resultByCondition = userMapper.paginate(1, 20, USER.AGE.ge(25));
// Pagination with known total count (optimized - skips count query)
Page<User> optimizedResult = userMapper.paginate(1, 10, 1000L,
QueryWrapper.create().from(User.class)
);
// Using Page object
Page<User> page = new Page<>(1, 10);
Page<User> result2 = userMapper.paginate(page,
QueryWrapper.create()
.from(User.class)
.where(USER.AGE.ge(18))
.orderBy(USER.NAME.asc())
);
// Pagination with field loading
Page<User> resultWithFields = userMapper.paginate(page,
QueryWrapper.create().from(User.class),
fieldQuery -> fieldQuery.load(USER.ORDERS).load(USER.PROFILE)
);
// Pagination with type conversion
Page<UserDto> dtoResult = userMapper.paginateAs(1, 10,
QueryWrapper.create()
.select(USER.ID, USER.NAME, USER.EMAIL)
.from(User.class),
UserDto.class
);
// Pagination with relationships and type conversion
Page<UserDto> dtoWithRelations = userMapper.paginateWithRelationsAs(1, 10,
QueryWrapper.create().from(User.class),
UserDto.class
);
// Complex pagination with all features
Page<UserDto> complexResult = userMapper.paginateWithRelationsAs(
new Page<>(2, 20), // Page 2, 20 records per page
QueryWrapper.create()
.from(User.class)
.where(USER.STATUS.eq("ACTIVE"))
.orderBy(USER.CREATED_AT.desc()),
UserDto.class,
fieldQuery -> fieldQuery.load(USER.ORDERS).load(USER.PROFILE)
);
System.out.println("Total records: " + complexResult.getTotalRow());
System.out.println("Total pages: " + complexResult.getTotalPage());
System.out.println("Current page: " + complexResult.getPageNumber());
List<UserDto> users = complexResult.getRecords();Support for custom XML-based queries with pagination, allowing integration with existing MyBatis XML mappers.
/**
* Paginate using XML mapper method with automatic count query
* @param dataSelectId XML select statement ID for data
* @param page pagination parameters
* @param queryWrapper query conditions passed to XML mapper
* @return page of results
*/
<E> Page<E> xmlPaginate(String dataSelectId, Page<E> page, QueryWrapper queryWrapper);
/**
* Paginate using XML mapper method with parameters
* @param dataSelectId XML select statement ID for data
* @param page pagination parameters
* @param otherParams additional parameters passed to XML mapper
* @return page of results
*/
<E> Page<E> xmlPaginate(String dataSelectId, Page<E> page, Map<String, Object> otherParams);
/**
* Paginate using XML mapper method with query wrapper and parameters
* @param dataSelectId XML select statement ID for data
* @param page pagination parameters
* @param queryWrapper query conditions passed to XML mapper
* @param otherParams additional parameters passed to XML mapper
* @return page of results
*/
<E> Page<E> xmlPaginate(String dataSelectId, Page<E> page, QueryWrapper queryWrapper, Map<String, Object> otherParams);
/**
* Paginate using XML mapper method with custom count query
* @param dataSelectId XML select statement ID for data
* @param countSelectId XML select statement ID for count query
* @param page pagination parameters
* @param queryWrapper query conditions passed to XML mapper
* @param otherParams additional parameters passed to XML mapper
* @return page of results
*/
<E> Page<E> xmlPaginate(String dataSelectId, String countSelectId, Page<E> page, QueryWrapper queryWrapper, Map<String, Object> otherParams);XML Pagination Examples:
// Basic XML pagination (uses dataSelectId + "_COUNT" for count query)
Page<User> xmlResult1 = userMapper.xmlPaginate("selectUsersByCondition",
new Page<>(1, 10),
QueryWrapper.create().where(USER.STATUS.eq("ACTIVE"))
);
// XML pagination with additional parameters
Map<String, Object> params = Map.of(
"minAge", 18,
"status", "ACTIVE",
"orderBy", "created_at DESC"
);
Page<User> xmlResult2 = userMapper.xmlPaginate("selectUsersWithParams",
new Page<>(1, 20),
params
);
// XML pagination with QueryWrapper and parameters
Page<User> xmlResult3 = userMapper.xmlPaginate("selectComplexUsers",
new Page<>(1, 15),
QueryWrapper.create().where(USER.AGE.between(18, 65)),
Map.of("includeDeleted", false)
);
// XML pagination with custom count query
Page<User> xmlResult4 = userMapper.xmlPaginate(
"selectUsersSummary", // Data select statement
"countUsersSummary", // Count select statement
new Page<>(1, 10),
QueryWrapper.create().where(USER.DEPARTMENT.eq("IT")),
Map.of("year", 2024)
);Example XML Mapper:
<!-- UserMapper.xml -->
<select id="selectUsersByCondition" resultType="User">
SELECT * FROM users
<where>
<if test="query != null">
${query.whereSql}
</if>
</where>
ORDER BY created_at DESC
</select>
<select id="selectUsersByCondition_COUNT" resultType="long">
SELECT COUNT(*) FROM users
<where>
<if test="query != null">
${query.whereSql}
</if>
</where>
</select>
<select id="selectUsersWithParams" resultType="User">
SELECT * FROM users
WHERE age >= #{minAge}
AND status = #{status}
${orderBy}
</select>// Pagination
public class Page<T> {
public Page(int pageNumber, int pageSize);
public Page(int pageNumber, int pageSize, boolean optimizeCountQuery);
public Page(Number pageNumber, Number pageSize);
public Page(Number pageNumber, Number pageSize, Number totalRow);
public List<T> getRecords();
public void setRecords(List<T> records);
public long getTotalRow();
public void setTotalRow(long totalRow);
public int getTotalPage();
public int getPageNumber();
public int getPageSize();
public boolean isOptimizeCountQuery();
public boolean hasRecords();
}
// Query conditions
public class QueryWrapper {
public static QueryWrapper create();
public QueryWrapper select(QueryColumn... columns);
public QueryWrapper from(Class<?> entityClass);
public QueryWrapper where(QueryCondition condition);
public QueryWrapper where(Map<String, Object> conditions);
public QueryWrapper and(QueryCondition condition);
public QueryWrapper or(QueryCondition condition);
public QueryWrapper orderBy(QueryColumn... columns);
public QueryWrapper limit(Number rows);
public QueryWrapper limit(Number offset, Number rows);
}
public class QueryCondition {
// Comparison conditions
public QueryCondition eq(Object value);
public QueryCondition ne(Object value);
public QueryCondition gt(Object value);
public QueryCondition ge(Object value);
public QueryCondition lt(Object value);
public QueryCondition le(Object value);
public QueryCondition like(String value);
public QueryCondition between(Object start, Object end);
public QueryCondition in(Object... values);
public QueryCondition in(Collection<?> values);
public QueryCondition isNull();
public QueryCondition isNotNull();
}
// Row operations (Map-like structure)
public class Row implements Map<String, Object> {
public static Row create();
public Row set(String key, Object value);
public <T> T get(String key, Class<T> type);
public String getString(String key);
public Integer getInt(String key);
public Long getLong(String key);
public Boolean getBoolean(String key);
public Date getDate(String key);
// ... implements Map<String, Object> methods
}
// Cursor for streaming results
public interface Cursor<T> extends Closeable, Iterable<T> {
boolean isOpen();
boolean isConsumed();
int getCurrentIndex();
}
// Field query builder for lazy loading
public interface FieldQueryBuilder<T> {
FieldQueryBuilder<T> load(QueryColumn field);
FieldQueryBuilder<T> load(String fieldName);
}
// Consumer interface for functional programming
public interface Consumer<T> {
void accept(T t);
}
// Collection types
public interface Collection<E> extends Iterable<E> {
int size();
boolean isEmpty();
boolean contains(Object o);
Object[] toArray();
boolean add(E e);
boolean remove(Object o);
// ... other collection methods
}
// Serializable for primary keys
public interface Serializable {
// Marker interface for primary key types
}
// Map for conditions and parameters
public interface Map<K, V> {
V get(Object key);
V put(K key, V value);
V remove(Object key);
boolean containsKey(Object key);
boolean containsValue(Object value);
Set<K> keySet();
Collection<V> values();
Set<Entry<K, V>> entrySet();
// ... other map methods
}Install with Tessl CLI
npx tessl i tessl/maven-com-mybatis-flex--mybatis-flex-core