baomidou/mybatis-plus · error · MybatisPlusException
Unable to get MybatisMapperProxy : {}
Error message
Unable to get MybatisMapperProxy : {} What it means
MybatisUtils.getMybatisMapperProxy(mapper) unwraps a mapper object down to the underlying MybatisMapperProxy (the JDK dynamic-proxy invocation target mybatis-plus generates). After stripping enhancement layers via extractMapperProxy, if the result is not a MybatisMapperProxy it throws MybatisPlusException('Unable to get MybatisMapperProxy : <mapper>'). This means the object passed in is not a mapper produced by a mybatis-plus SqlSessionFactory.
Source
Thrown at mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/MybatisUtils.java:151
}
SqlSessionFactory sqlSessionFactory = GlobalConfigUtils.getGlobalConfig(sqlSession.getConfiguration()).getSqlSessionFactory();
Assert.isTrue(sqlSessionFactory != null, "Please implement access to the sqlSessionFactory property or bind sqlSessionFactory to global access.");
return sqlSessionFactory;
}
/**
* 获取代理实现
*
* @param mapper mapper类
* @return 代理实现
* @since 3.5.7
*/
public static MybatisMapperProxy<?> getMybatisMapperProxy(Object mapper) {
Object result = extractMapperProxy(mapper);
if (result instanceof MybatisMapperProxy) {
return (MybatisMapperProxy<?>) result;
}
throw new MybatisPlusException("Unable to get MybatisMapperProxy : " + mapper);
}
/**
* 提取MapperProxy
*
* @param mapper Mapper对象
* @return 真实Mapper对象(去除动态代理增强)
* @since 3.5.12
*/
public static Object extractMapperProxy(Object mapper) {
if (mapper instanceof MybatisMapperProxy) {
// fast return
return mapper;
}
Object result = mapper;
if (CompatibleHelper.hasCompatibleSet()) {
Object proxyTargetObject = CompatibleHelper.getCompatibleSet().getProxyTargetObject(result);
if (proxyTargetObject != null) {View on GitHub (pinned to bf67d90747)
Solutions
- Verify the object actually came from a mybatis-plus SqlSessionFactory (getMapper on a MybatisSqlSessionFactoryBean-built factory).
- In tests, inject a real mapper (e.g. @MybatisPlusTest / spring test slice) instead of a Mockito mock when the code path calls getMybatisMapperProxy.
- Unwrap outer AOP/aspect layers first — extractMapperProxy can only strip layers it recognizes; keep your own unwrapping for exotic proxies.
- Defensively check with instanceof MybatisMapperProxy before calling if the mapper provenance is uncertain.
Example fix
// before
MybatisMapperProxy<?> proxy = MybatisUtils.getMybatisMapperProxy(maybeMock); // throws in unit tests
// after
Object raw = MybatisUtils.extractMapperProxy(maybeMock);
if (raw instanceof MybatisMapperProxy) {
MybatisMapperProxy<?> proxy = (MybatisMapperProxy<?>) raw;
// ...
} else {
throw new IllegalStateException("not a mybatis-plus mapper: " + maybeMock);
} Defensive patterns
Strategy: type-guard
Validate before calling
Object raw = MybatisUtils.extractMapperProxy(mapper);
if (!(raw instanceof MybatisMapperProxy)) {
throw new IllegalStateException("Not a mybatis-plus mapper: " + mapper.getClass());
} Type guard
static boolean isMybatisPlusMapper(Object o) {
if (o == null) return false;
if (o instanceof MybatisMapperProxy) return true;
if (Proxy.isProxyClass(o.getClass())) {
return Proxy.getInvocationHandler(o) instanceof MybatisMapperProxy;
}
return MybatisUtils.extractMapperProxy(o) instanceof MybatisMapperProxy;
} Try / catch
try {
MybatisMapperProxy<?> p = MybatisUtils.getMybatisMapperProxy(mapper);
} catch (MybatisPlusException e) {
throw new IllegalStateException("Expected a mapper obtained from a mybatis-plus SqlSessionFactory", e);
} Prevention
- Only pass mappers obtained from a mybatis-plus SqlSessionFactory.
- In tests, use real mapper slices rather than mocks where proxy extraction is involved.
When it happens
Trigger: Passing a non-mapper object, a plain MyBatis (non-plus) mapper proxy, or a mock/stub to getMybatisMapperProxy; also calling it before the mapper has been created through mybatis-plus's configuration, or on a bean wrapped by AOP proxies whose invocation handler chain does not terminate in a MybatisMapperProxy.
Common situations: Mockito mocks injected where a real mapper is expected in a service test; mixing stock mybatis and mybatis-plus on the same classpath so some mappers are plain org.apache.ibatis proxies; customlazy-enhancement proxies that hide the underlying invocation handler.
Related errors
- Failed to create a new Configuration instance.
- Unable to retrieve the mapperInterface and sqlSession proper
- Cannot find class: {}
- Failed invoking constructor for handler {}
- %s already contains value for %s
AI-assisted analysis of baomidou/mybatis-plus@bf67d90747 (2026-08-14).
Data as JSON: /api/errors/3e803b30d432097d.
Report an issue: GitHub.