MyBatis-Plus Enum TypeHandler Bug Caused by Anonymous Enum Instances and How to Resolve It
This article investigates a MyBatis‑Plus bug where enum values with abstract methods become anonymous classes, causing the framework to fail to locate the correct TypeHandler, leading to SQL errors, and provides several practical solutions to avoid or fix the issue.
When using mybatis-plus to perform a CRUD operation, an exception occurs because the status column in the database is defined as an integer, but the enum value COMPLETED (a string) is being passed.
The error manifests after a project restart when updateById() is called, and subsequent calls to selectById() produce a ResultMapException indicating that the enum constant cannot be found.
Debugging shows that the enum TaskStatusEnum is compiled into anonymous classes (e.g., TaskStatusEnum$2.class) because each enum constant implements an abstract method. This leads MyBatis‑Plus to look up a TypeHandler for the anonymous class, which fails, causing the framework to fall back to the default EnumTypeHandler that cannot handle the anonymous type.
Source code excerpts illustrate the problematic method and the resulting SQL exception:
@Transactional
@Override
public boolean updateTaskStatus(Integer taskId, TaskStatusEnum taskStatusEnum) {
// 查询任务
Task task = taskMapper.selectById(taskId);
if (Objects.isNull(task)) {
throw new IllegalArgumentException("没有查询到任务!");
}
// 检查状态是否正常
if (!task.getStatus().nextStatus().contains(taskStatusEnum)) {
throw new IllegalStateException("不能修改当前任务的状态!");
}
// 状态正常就修改状态到下一个状态
task.setStatus(taskStatusEnum);
// 更新任务状态
int result = taskMapper.updateById(task);
return result > 0;
}The root cause is that MyBatis‑Plus retrieves a TypeHandler based on the runtime type of the parameter. For anonymous enum instances, the registry cannot find a matching handler, and the default handler is registered for the parent enum class, which then gets overwritten by the failed lookup.
Comparing with plain MyBatis reveals that MyBatis caches the TypeHandler for the entity field at startup and does not depend on the runtime parameter type, avoiding this issue. MyBatis‑Plus, however, wraps parameters in a ParamMap, causing the runtime type to be Object.class and breaking the handler lookup.
To avoid the bug, the article suggests several solutions:
Do not define abstract methods in enums, preventing the creation of anonymous enum classes.
Configure a TypeHandler for the parent interface so that anonymous classes can inherit it.
Dynamically register a TypeHandler for all anonymous enum types via TypeHandlerRegistry.register.
Replace MyBatis‑Plus with plain MyBatis if feasible, though this may require extensive code changes.
These steps ensure that the correct TypeHandler is used, eliminating the SQL errors caused by mismatched enum handling.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Selected Java Interview Questions
A professional Java tech channel sharing common knowledge to help developers fill gaps. Follow us!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
