baomidou/mybatis-plus · error · UnsupportedOperationException
不支持的方法!
Error message
不支持的方法!
What it means
IRepository.removeById(Serializable id, boolean useFill) defaults to throwing UnsupportedOperationException('不支持的方法!' — 'Unsupported method!'). The base IRepository interface only implements the common path; the fill-aware variant (which converts the id to an entity to run fill logic before delete) is only meaningful for implementations backed by a full ServiceImpl-style repository. Calling it on the default interface, or on a custom implementation that does not override it, explodes.
Source
Thrown at mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/repository/IRepository.java:74
/**
* 根据 ID 删除
*
* @param id 主键ID
*/
default boolean removeById(Serializable id) {
return SqlHelper.retBool(getBaseMapper().deleteById(id));
}
/**
* 根据 ID 删除
*
* @param id 主键(类型必须与实体类型字段保持一致)
* @param useFill 是否启用填充(为true的情况,会将入参转换实体进行delete删除)
* @return 删除结果
* @since 3.5.0
*/
default boolean removeById(Serializable id, boolean useFill) {
throw new UnsupportedOperationException("不支持的方法!");
}
/**
* 根据实体(ID)删除
*
* @param entity 实体
* @since 3.4.4
*/
default boolean removeById(T entity) {
return SqlHelper.retBool(getBaseMapper().deleteById(entity));
}
/**
* 根据 columnMap 条件,删除记录
*
* @param columnMap 表字段 map 对象
*/
default boolean removeByMap(Map<String, Object> columnMap) {View on GitHub (pinned to bf67d90747)
Solutions
- Override removeById(Serializable id, boolean useFill) in your IRepository implementation, implementing the fill path (convert id to entity, apply meta-object fill, delete).
- Or call the supported variant removeById(id) (single-argument) which routes to getBaseMapper().deleteById(id) directly.
- If fill-on-delete is required, extend the provided ServiceImpl/repository base class that already implements it.
- In tests, use Mockito with CALLS_REAL_METHODS awareness or explicitly stub the two-argument variant.
Example fix
// before: custom repo does not override fill variant
public class UserRepository implements IRepository<User> {
// removeById(id, useFill) inherited default -> UnsupportedOperationException
}
// after: override it
public class UserRepository implements IRepository<User> {
@Override
public boolean removeById(Serializable id, boolean useFill) {
if (!useFill) return SqlHelper.retBool(getBaseMapper().deleteById(id));
User entity = getById(id);
return SqlHelper.retBool(getBaseMapper().deleteById(entity));
}
} Defensive patterns
Strategy: type-guard
Validate before calling
IRepository<User> repo = acquireRepository();
boolean fillVariantSupported;
try {
repo.getClass().getMethod("removeById", Serializable.class, boolean.class)
.getDeclaringClass();
fillVariantSupported = !IRepository.class.equals(
repo.getClass().getMethod("removeById", Serializable.class, boolean.class).getDeclaringClass());
} catch (NoSuchMethodException e) { fillVariantSupported = false; }
if (!fillVariantSupported) repo.removeById(id); // use supported single-arg variant Type guard
static boolean supportsRemoveByIdWithFill(Object repo) {
try {
Method m = repo.getClass().getMethod("removeById", Serializable.class, boolean.class);
return !m.getDeclaringClass().isInterface(); // real override, not default
} catch (NoSuchMethodException e) {
return false;
}
} Try / catch
try {
repository.removeById(id, true);
} catch (UnsupportedOperationException e) {
repository.removeById(id); // fall back to the always-supported variant
} Prevention
- Override the two-argument removeById in custom IRepository implementations, or extend the provided base classes.
- Prefer the single-argument removeById unless fill-on-delete is explicitly required.
When it happens
Trigger: Holding an IRepository (or a custom implementation of it) and calling removeById(id, true) — the two-argument fill variant — without the concrete class overriding that default method. Introduced in 3.5.0; implementations like the standard repository/service impl override it, minimal custom ones do not.
Common situations: Custom IRepository implementations (e.g. a thin repository over a base mapper) written against an older API surface, then new code calls the 3.5.0 fill variant; switching a bean from ServiceImpl to a hand-written repository loses the override; mocking IRepository in tests without stubbing the default method (some mock libs invoke real defaults).
AI-assisted analysis of baomidou/mybatis-plus@bf67d90747 (2026-08-14).
Data as JSON: /api/errors/24551a3e68fc1e65.
Report an issue: GitHub.