TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 3

  • Post author:
  • Post category:其他


根本原因:返回值类型为一个,例如Integer或者实体类,但是sql查询结果(selectOne#selectList)为多个。

mybits,mapper方法底层源码

五种sql类型:insert、update、delete、select、flush

  public Object execute(SqlSession sqlSession, Object[] args) {
    Object result;
    //sql类型
    switch (command.getType()) {
      case INSERT: {
    	Object param = method.convertArgsToSqlCommandParam(args);
        result = rowCountResult(sqlSession.insert(command.getName(), param));
        break;
      }
      case UPDATE: {
        Object param = method.convertArgsToSqlCommandParam(args);
        result = rowCountResult(sqlSession.update(command.getName(), param));
        break;
      }
      case DELETE: {
        Object param = method.convertArgsToSqlCommandParam(args);
        result = rowCountResult(sqlSession.delete(command.getName(), param));
        break;
      }
      case SELECT:
        if (method.returnsVoid() && method.hasResultHandler()) {
          executeWithResultHandler(sqlSession, args);
          result = null;
        } else if (method.returnsMany()) {
          result = executeForMany(sqlSession, args);
        } else if (method.returnsMap()) {
          result = executeForMap(sqlSession, args);
        } else if (method.returnsCursor()) {
          result = executeForCursor(sqlSession, args);
        } else {
          Object param = method.convertArgsToSqlCommandParam(args);
          result = sqlSession.selectOne(command.getName(), param);
        }
        break;
      case FLUSH:
        result = sqlSession.flushStatements();
        break;
      default:
        throw new BindingException("Unknown execution method for: " + command.getName());
    }
    if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) {
      throw new BindingException("Mapper method '" + command.getName() 
          + " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ").");
    }
    return result;
  }

select的返回类型:

1. void

this.returnsVoid = Void.TYPE.equals(this.returnType);

2. list或array

this.returnsMany = configuration.getObjectFactory().isCollection(this.returnType) || this.returnType.isArray();

3. map

this.mapKey = this.getMapKey(method);
this.returnsMap = this.mapKey != null;

private String getMapKey(Method method) {
    String mapKey = null;
    //map类型
    if (Map.class.isAssignableFrom(method.getReturnType())) {
        MapKey mapKeyAnnotation = (MapKey)method.getAnnotation(MapKey.class);
        if (mapKeyAnnotation != null) {
            mapKey = mapKeyAnnotation.value();
        }
    }

    return mapKey;
}

4. 游标cursor

this.returnsCursor = Cursor.class.equals(this.returnType);

5. 以上三种都不是,那就是selectOne

查询结果用list接收

    public <T> T selectOne(String statement, Object parameter) {
        //查询结果用list接收
        List<T> list = this.selectList(statement, parameter);
        if (list.size() == 1) {
            return list.get(0);
        } else if (list.size() > 1) {
            throw new TooManyResultsException("Expected one result (or null) to be returned by selectOne(), but found: " + list.size());
        } else {
            return null;
        }
    }


    public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
        List var5;
        try {
            MappedStatement ms = this.configuration.getMappedStatement(statement);
            //查询
            var5 = this.executor.query(ms, this.wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
        } catch (Exception var9) {
            throw ExceptionFactory.wrapException("Error querying database.  Cause: " + var9, var9);
        } finally {
            ErrorContext.instance().reset();
        }

        return var5;
    }

疑问:sql中distinct的情况下,上述selectList返回的结果到底是distinct前的还是distinct后的?

本地测试结果,

distinct后的

数据如下:

测试结果:



版权声明:本文为tec_1535原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。