{"record":{"id":"5d89810be6b941d1","repo":"baomidou/mybatis-plus","slug":"expected-one-result-or-null-to-be-returned-by-se","errorCode":null,"errorMessage":"Expected one result (or null) to be returned by selectOne(), but found: %s","messagePattern":"Expected one result \\(or null\\) to be returned by selectOne\\(\\), but found: (.+?)","errorType":"exception","errorClass":"TooManyResultsException","httpStatus":null,"severity":"error","filePath":"mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/mapper/BaseMapper.java","lineNumber":341,"sourceCode":"    default T selectOne(Wrapper<T> queryWrapper) {\n        return this.selectOne(queryWrapper, true);\n    }\n\n    /**\n     * 根据 entity 条件，查询一条记录，现在会根据{@code throwEx}参数判断是否抛出异常，如果为false就直接返回一条数据\n     * <p>查询一条记录，例如 qw.last(\"limit 1\") 限制取一条记录, 注意：多条数据会报异常</p>\n     *\n     * @param queryWrapper 实体对象封装操作类（可以为 null）\n     * @param throwEx      boolean 参数，为true如果存在多个结果直接抛出异常\n     */\n    default T selectOne(Wrapper<T> queryWrapper, boolean throwEx) {\n        List<T> list = this.selectList(queryWrapper);\n        int size = list.size();\n        if (size == 1) {\n            return list.get(0);\n        } else if (size > 1) {\n            if (throwEx) {\n                throw new TooManyResultsException(\"Expected one result (or null) to be returned by selectOne(), but found: \" + size);\n            }\n            return list.get(0);\n        }\n        return null;\n    }\n\n    /**\n     * 根据 Wrapper 条件，游标方式查询全部记录\n     * <p>注意！需要在事务中 @Transactional 注解方法，或者手动管理 sqlSession 避免会话中断</p>\n     *\n     * @param queryWrapper 实体对象封装操作类（可以为 null）\n     */\n    Cursor<T> selectWithCursor(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);\n\n    /**\n     * 根据 Wrapper 条件，判断是否存在记录\n     *\n     * @param queryWrapper 实体对象封装操作类","sourceCodeStart":323,"sourceCodeEnd":359,"githubUrl":"https://github.com/baomidou/mybatis-plus/blob/bf67d907478c724120bf76292da54abf9e73c2b3/mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/mapper/BaseMapper.java#L323-L359","documentation":"BaseMapper.selectOne(wrapper, throwEx=true) executed the query, received more than one row, and threw TooManyResultsException because strict mode was requested. With throwEx=false it would silently return the first row; the boolean overload exists to make one-row expectations explicit.","triggerScenarios":"Calling selectOne(queryWrapper, true) where the query matches 2+ rows — e.g. a unique-ish filter that is not actually unique, or missing a limit while duplicate data exists.","commonSituations":"Assuming a field is unique when the table contains duplicates; race between check and insert creating duplicates; upgrading code from selectOne(wrapper) (which also throws by default in MyBatis) and hitting dirty data.","solutions":["Decide intent: if duplicates are legitimate, pass throwEx=false or add qw.last(\"LIMIT 1\")","If one row is the contract, fix the data (add a unique constraint) and the query predicate so it truly selects one row","Inspect the rows returned by the same wrapper via selectList to understand the duplication"],"exampleFix":"// before\nUser u = userMapper.selectOne(qw, true); // throws if duplicates exist\n// after (dupes acceptable, want first)\nUser u = userMapper.selectOne(qw.last(\"LIMIT 1\"));\n// after (dupes are a bug)\n// dedupe data + ALTER TABLE user ADD UNIQUE KEY uk_email (email);","handlingStrategy":"validation","validationCode":"// Pre-check when duplicates are possible\nLong cnt = userMapper.selectCount(qw);\nif (cnt != null && cnt > 1) {\n    // decide: first row, or fail with context\n    log.warn(\"selectOne matched {} rows\", cnt);\n}\nUser u = cnt != null && cnt == 1 ? userMapper.selectOne(qw) : userMapper.selectOne(qw.last(\"LIMIT 1\"));","typeGuard":null,"tryCatchPattern":"try { return userMapper.selectOne(qw, true); } catch (TooManyResultsException e) { log.warn(\"Duplicate rows for filter, returning first\"); return userMapper.selectOne(qw.last(\"LIMIT 1\")); } // only when duplicates are acceptable","preventionTips":["Enforce uniqueness in the schema (unique constraints) for fields used in selectOne filters","Prefer selectOne(qw.last(\"LIMIT 1\")) when the data model allows ties","Add data-quality checks/alerts on tables queried with selectOne"],"tags":["mybatis","select-one","too-many-results","data-quality"],"backgroundTag":null,"analyzedSha":"bf67d907478c724120bf76292da54abf9e73c2b3","analyzedAt":"2026-08-14T15:17:09.543Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}