MyBatis-Plus is an enhanced toolkit for MyBatis providing CRUD operations, query wrappers, pagination, code generation, and Spring Boot integration.
—
MyBatis-Plus provides automatic CRUD operations through the BaseMapper interface, eliminating the need to write basic SQL statements while maintaining full type safety and MyBatis compatibility.
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.annotations.Param;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;The core mapper interface providing comprehensive database operations with automatic SQL generation.
/**
* Base mapper interface providing CRUD operations for entity type T
* @param <T> Entity type
*/
public interface BaseMapper<T> {
/**
* Insert a record
* @param entity Entity object to insert
* @return Number of affected rows
*/
int insert(T entity);
/**
* Delete by primary key
* @param id Primary key value
* @return Number of affected rows
*/
int deleteById(Serializable id);
/**
* Delete by column map conditions
* @param columnMap Column conditions map
* @return Number of affected rows
*/
int deleteByMap(@Param("cm") Map<String, Object> columnMap);
/**
* Delete by query wrapper conditions
* @param queryWrapper Query conditions wrapper
* @return Number of affected rows
*/
int delete(@Param("ew") Wrapper<T> queryWrapper);
/**
* Delete multiple records by primary keys
* @param idList Collection of primary key values
* @return Number of affected rows
*/
int deleteBatchIds(@Param("coll") Collection<? extends Serializable> idList);
/**
* Update by primary key
* @param entity Entity object with primary key
* @return Number of affected rows
*/
int updateById(@Param("et") T entity);
/**
* Update by conditions
* @param entity Entity object with new values
* @param updateWrapper Update conditions wrapper
* @return Number of affected rows
*/
int update(@Param("et") T entity, @Param("ew") Wrapper<T> updateWrapper);
/**
* Select by primary key
* @param id Primary key value
* @return Entity object or null
*/
T selectById(Serializable id);
/**
* Select multiple records by primary keys
* @param idList Collection of primary key values
* @return List of entities
*/
List<T> selectBatchIds(@Param("coll") Collection<? extends Serializable> idList);
/**
* Select by column map conditions
* @param columnMap Column conditions map
* @return List of entities
*/
List<T> selectByMap(@Param("cm") Map<String, Object> columnMap);
/**
* Select one record by query wrapper conditions
* @param queryWrapper Query conditions wrapper
* @return Single entity or null
*/
T selectOne(@Param("ew") Wrapper<T> queryWrapper);
/**
* Count records by query wrapper conditions
* @param queryWrapper Query conditions wrapper
* @return Total count
*/
Long selectCount(@Param("ew") Wrapper<T> queryWrapper);
/**
* Select list by query wrapper conditions
* @param queryWrapper Query conditions wrapper
* @return List of entities
*/
List<T> selectList(@Param("ew") Wrapper<T> queryWrapper);
/**
* Select list of maps by query wrapper conditions
* @param queryWrapper Query conditions wrapper
* @return List of maps representing records
*/
List<Map<String, Object>> selectMaps(@Param("ew") Wrapper<T> queryWrapper);
/**
* Select list of objects by query wrapper conditions
* @param queryWrapper Query conditions wrapper
* @return List of objects (typically for single column selection)
*/
List<Object> selectObjs(@Param("ew") Wrapper<T> queryWrapper);
/**
* Select paginated records
* @param page Pagination parameters
* @param queryWrapper Query conditions wrapper
* @return Paginated results
*/
<P extends IPage<T>> P selectPage(P page, @Param("ew") Wrapper<T> queryWrapper);
/**
* Select paginated maps
* @param page Pagination parameters
* @param queryWrapper Query conditions wrapper
* @return Paginated map results
*/
<P extends IPage<Map<String, Object>>> P selectMapsPage(P page, @Param("ew") Wrapper<T> queryWrapper);
/**
* Check if record exists by query wrapper conditions
* @param queryWrapper Query conditions wrapper
* @return true if record exists, false otherwise
*/
boolean exists(@Param("ew") Wrapper<T> queryWrapper);
/**
* Select one record with exception control
* @param queryWrapper Query conditions wrapper
* @param throwEx Whether to throw exception if multiple records found
* @return Single entity or null
*/
T selectOne(@Param("ew") Wrapper<T> queryWrapper, boolean throwEx);
/**
* Delete by primary key with fill strategy
* @param id Primary key value
* @param useFill Whether to apply auto-fill for deletion
* @return Number of affected rows
*/
int deleteById(Serializable id, boolean useFill);
/**
* Delete multiple records by primary keys with fill strategy
* @param idList Collection of primary key values
* @param useFill Whether to apply auto-fill for deletion
* @return Number of affected rows
*/
int deleteBatchIds(@Param("coll") Collection<? extends Serializable> idList, boolean useFill);
/**
* Select with result handler for memory-efficient processing
* @param queryWrapper Query conditions wrapper
* @param handler Result handler for streaming processing
*/
void selectList(@Param("ew") Wrapper<T> queryWrapper, ResultHandler<T> handler);
/**
* Select batch IDs with result handler
* @param idList Collection of primary key values
* @param handler Result handler for streaming processing
*/
void selectBatchIds(@Param("coll") Collection<? extends Serializable> idList, ResultHandler<T> handler);
}Basic Setup:
// Entity class
@TableName("user")
public class User {
@TableId(type = IdType.AUTO)
private Long id;
private String name;
private Integer age;
private String email;
// constructors, getters, setters...
}
// Mapper interface
@Mapper
public interface UserMapper extends BaseMapper<User> {
// Inherits all BaseMapper methods
// Custom methods can be added here
}Insert Operations:
@Autowired
private UserMapper userMapper;
// Insert single record
User user = new User();
user.setName("John Doe");
user.setAge(25);
user.setEmail("john@example.com");
int result = userMapper.insert(user);
// result = 1 if successful
// user.getId() will contain the generated ID if using AUTO incrementDelete Operations:
// Delete by primary key
int result = userMapper.deleteById(1L);
// Delete by conditions map
Map<String, Object> conditions = new HashMap<>();
conditions.put("age", 25);
conditions.put("name", "John");
int result = userMapper.deleteByMap(conditions);
// Delete by query wrapper
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("age", 25).like("name", "John");
int result = userMapper.delete(wrapper);
// Delete multiple by IDs
List<Long> ids = Arrays.asList(1L, 2L, 3L);
int result = userMapper.deleteBatchIds(ids);Update Operations:
// Update by primary key (only non-null fields are updated)
User user = new User();
user.setId(1L);
user.setAge(26); // Only age will be updated
int result = userMapper.updateById(user);
// Update with conditions
User user = new User();
user.setAge(26);
UpdateWrapper<User> wrapper = new UpdateWrapper<>();
wrapper.eq("name", "John").lt("age", 30);
int result = userMapper.update(user, wrapper);Select Operations:
// Select by primary key
User user = userMapper.selectById(1L);
// Select multiple by IDs
List<Long> ids = Arrays.asList(1L, 2L, 3L);
List<User> users = userMapper.selectBatchIds(ids);
// Select by conditions map
Map<String, Object> conditions = new HashMap<>();
conditions.put("age", 25);
List<User> users = userMapper.selectByMap(conditions);
// Select with query wrapper
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("age", 25).orderByDesc("id").last("LIMIT 10");
List<User> users = userMapper.selectList(wrapper);
// Select one record
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("email", "john@example.com");
User user = userMapper.selectOne(wrapper);
// Count records
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.gt("age", 18);
Long count = userMapper.selectCount(wrapper);
// Select as maps
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.select("name", "age").gt("age", 18);
List<Map<String, Object>> maps = userMapper.selectMaps(wrapper);
// Select objects (for single column)
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.select("name").gt("age", 18);
List<Object> names = userMapper.selectObjs(wrapper);
// Paginated select
Page<User> page = new Page<>(1, 10); // current page, page size
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.gt("age", 18).orderByDesc("id");
IPage<User> userPage = userMapper.selectPage(page, wrapper);
System.out.println("Total: " + userPage.getTotal());
System.out.println("Records: " + userPage.getRecords().size());Enhanced Operations (MyBatis-Plus 3.5.7+):
// Check if record exists
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("email", "john@example.com");
boolean exists = userMapper.exists(wrapper);
// Select one with exception control
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.like("name", "John");
User user = userMapper.selectOne(wrapper, false); // Won't throw exception if multiple found
// Delete with fill strategy (useful with @TableLogic)
int result = userMapper.deleteById(1L, true); // Apply auto-fill for logical deletion
// Batch delete with fill strategy
List<Long> ids = Arrays.asList(1L, 2L, 3L);
int result = userMapper.deleteBatchIds(ids, true);
// Memory-efficient processing with ResultHandler
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.gt("age", 18);
userMapper.selectList(wrapper, new ResultHandler<User>() {
@Override
public void handleResult(ResultContext<? extends User> resultContext) {
User user = resultContext.getResultObject();
// Process each user individually without loading all into memory
processUser(user);
}
});
// Stream processing for large batch operations
List<Long> largeIdList = getLargeIdList(); // Thousands of IDs
userMapper.selectBatchIds(largeIdList, user -> {
// Process each user as it's retrieved
processUser(user);
});All BaseMapper methods may throw MyBatisSystemException or its subclasses for SQL execution errors. Common scenarios:
try {
userMapper.insert(user);
} catch (MyBatisSystemException e) {
// Handle database errors
log.error("Failed to insert user", e);
throw new ServiceException("User creation failed", e);
}deleteBatchIds() and selectBatchIds() for multiple recordsupdateById() only updates non-null fields by defaultselectMaps() or selectObjs() for partial column selectionInstall with Tessl CLI
npx tessl i tessl/maven-com-baomidou--mybatis-plus