Как обработать результат карты (результаты с двумя столбцами), используя интерфейс mybatis, а не sqlSession - PullRequest
0 голосов
/ 06 января 2019

Я использую Spring boot и Mybatis (interface и mapper.xml) в веб-приложении java.

Моя цель - преобразовать список результатов, содержащий два столбца 'name' и 'count', в карту. Первый столбец должен использоваться как ключ, а второй столбец - как значение в этой карте.

Я знаю, что мне следует переписать ResultHandler, в то время как, как это может повлиять на использование интерфейса?

Ответы [ 2 ]

0 голосов
/ 16 января 2019

Самый простой способ сделать это - использовать метод интерфейса по умолчанию для преобразования:

interfact MyMapper {

  @Select("SELECT name, count FROM whatever")
  List<Map<String, Object>> findCountsList();

  default Map<String, Integer> findCounts() {
      Map<String, Integer> result = new HashMap<>;
      for(Map<String, Object> entry:findCountsList()) {
          result.put(entry.get("name"), ((Number)entry.get("count")).intValue());
      }
      return result;
  }

}
0 голосов
/ 16 января 2019

Обновлен. Я реализовал этот метод, добавив Interceptor для обработки этих случаев и добавив плагин в mybatis-config.xml, чтобы включить его.

Сначала создайте аннотацию, затем вы можете обработать этот случай, добавив аннотацию, перезаписав ее и задав первый столбец в качестве ключа, а второй столбец в качестве значения.

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
@Inherited
public @interface ResultMap {

    String value();
}

Во-вторых, вы должны реализовать перехватчик для обработки mybatis resultSet с аннотацией @ResultMap

public class ResultMapInterceptor implements Interceptor {

    private static final Logger LOGGER = LoggerFactory.getLogger(ResultMapInterceptor.class);

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object target = invocation.getTarget();
        DefaultResultSetHandler defaultResultSetHandler = (DefaultResultSetHandler) target;
        Field field = ReflectionUtils.findField(DefaultResultSetHandler.class, "mappedStatement");
        ReflectionUtils.makeAccessible(field);
        MappedStatement mappedStatement = (MappedStatement) field.get(defaultResultSetHandler);
        String className = StringUtils.substringBeforeLast(mappedStatement.getId(), ".");
        String methodName = StringUtils.substringAfterLast(mappedStatement.getId(), ".");

        Method[] methods = Class.forName(className).getDeclaredMethods();
        if (methods == null) {
            return invocation.proceed();
        }

        // get method "mappedStatement"
        for (Method method : methods) {
            if (methodName.equalsIgnoreCase(method.getName())) {
                // get annotation ResultMap, if null, then proceed
                ResultMap resultMap = method.getAnnotation(ResultMap.class);
                if (resultMap == null) {
                    return invocation.proceed();
                }
                // convert result map to specify result
                Statement statement = (Statement) invocation.getArgs()[0];
                return convert2Map(statement);
            }
        }
        return invocation.proceed();
    }

    @Override
    public Object plugin(Object target) {
        if (target instanceof ResultSetHandler) {
            return Plugin.wrap(target, this);
        } else {
            return target;
        }
    }

    @Override
    public void setProperties(Properties properties) {

    }

    private Object convert2Map(Statement statement) throws Throwable{
        ResultSet resultSet = statement.getResultSet();
        if (resultSet == null) {
            return null;
        }
        List<Object> resultList = new ArrayList(4);
        Map<Object, Object> map = new HashMap(8);
        while (resultSet.next()) {
            if (resultSet.getObject(1) != null) {
                map.put(resultSet.getObject(1), resultSet.getObject(2));
            }
        }
        resultList.add(map);
        LOGGER.debug("map result from DB, {}", resultList);
        return resultList;
    }

Затем включите этот перехватчик, добавив плагины в mybatis-config.xml

</configuration>
   <plugins>
        <plugin interceptor="com.cisco.migration.handler.ResultMapInterceptor"/>
    </plugins>
</configuration>

Наконец, используйте эту аннотацию в интерфейсе mybatis dao.

@ResultMap("")
Map getCountByAccType(SearchFilter searchFilter);

mapper.xml

<select id="getCountByAccType" resultMap="resultMap">
        select
            id,
            count(ACCOUNTTYPE) count
        from table t
</select>
...