{"record":{"id":"3e803b30d432097d","repo":"baomidou/mybatis-plus","slug":"unable-to-get-mybatismapperproxy","errorCode":null,"errorMessage":"Unable to get MybatisMapperProxy : {}","messagePattern":"Unable to get MybatisMapperProxy : (.+?)","errorType":"exception","errorClass":"MybatisPlusException","httpStatus":null,"severity":"error","filePath":"mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/MybatisUtils.java","lineNumber":151,"sourceCode":"        }\n        SqlSessionFactory sqlSessionFactory = GlobalConfigUtils.getGlobalConfig(sqlSession.getConfiguration()).getSqlSessionFactory();\n        Assert.isTrue(sqlSessionFactory != null, \"Please implement access to the sqlSessionFactory property or bind sqlSessionFactory to global access.\");\n        return sqlSessionFactory;\n    }\n\n    /**\n     * 获取代理实现\n     *\n     * @param mapper mapper类\n     * @return 代理实现\n     * @since 3.5.7\n     */\n    public static MybatisMapperProxy<?> getMybatisMapperProxy(Object mapper) {\n        Object result = extractMapperProxy(mapper);\n        if (result instanceof MybatisMapperProxy) {\n            return (MybatisMapperProxy<?>) result;\n        }\n        throw new MybatisPlusException(\"Unable to get MybatisMapperProxy : \" + mapper);\n    }\n\n    /**\n     * 提取MapperProxy\n     *\n     * @param mapper Mapper对象\n     * @return 真实Mapper对象(去除动态代理增强)\n     * @since 3.5.12\n     */\n    public static Object extractMapperProxy(Object mapper) {\n        if (mapper instanceof MybatisMapperProxy) {\n            // fast return\n            return mapper;\n        }\n        Object result = mapper;\n        if (CompatibleHelper.hasCompatibleSet()) {\n            Object proxyTargetObject = CompatibleHelper.getCompatibleSet().getProxyTargetObject(result);\n            if (proxyTargetObject != null) {","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/baomidou/mybatis-plus/blob/bf67d907478c724120bf76292da54abf9e73c2b3/mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/MybatisUtils.java#L133-L169","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nMybatisMapperProxy<?> proxy = MybatisUtils.getMybatisMapperProxy(maybeMock); // throws in unit tests\n\n// after\nObject raw = MybatisUtils.extractMapperProxy(maybeMock);\nif (raw instanceof MybatisMapperProxy) {\n    MybatisMapperProxy<?> proxy = (MybatisMapperProxy<?>) raw;\n    // ...\n} else {\n    throw new IllegalStateException(\"not a mybatis-plus mapper: \" + maybeMock);\n}","handlingStrategy":"type-guard","validationCode":"Object raw = MybatisUtils.extractMapperProxy(mapper);\nif (!(raw instanceof MybatisMapperProxy)) {\n    throw new IllegalStateException(\"Not a mybatis-plus mapper: \" + mapper.getClass());\n}","typeGuard":"static boolean isMybatisPlusMapper(Object o) {\n    if (o == null) return false;\n    if (o instanceof MybatisMapperProxy) return true;\n    if (Proxy.isProxyClass(o.getClass())) {\n        return Proxy.getInvocationHandler(o) instanceof MybatisMapperProxy;\n    }\n    return MybatisUtils.extractMapperProxy(o) instanceof MybatisMapperProxy;\n}","tryCatchPattern":"try {\n    MybatisMapperProxy<?> p = MybatisUtils.getMybatisMapperProxy(mapper);\n} catch (MybatisPlusException e) {\n    throw new IllegalStateException(\"Expected a mapper obtained from a mybatis-plus SqlSessionFactory\", e);\n}","preventionTips":["Only pass mappers obtained from a mybatis-plus SqlSessionFactory.","In tests, use real mapper slices rather than mocks where proxy extraction is involved."],"tags":["mapper-proxy","reflection","testing","configuration"],"backgroundTag":null,"analyzedSha":"bf67d907478c724120bf76292da54abf9e73c2b3","analyzedAt":"2026-08-14T15:17:09.543Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}