Mybatis 可以支持将动态列映射到 bean 的映射字段吗?

can Mybatis support mapping the dynamic columns to an map field of a bean?

我有一个要求,可能有点复杂。想想我有豆 class 喜欢:

public class A {
   private String column1;
   private String column2;
   private Map<String,String> dynamicColumns = Maps.newHashMap();
   ....
   getter&setter of column1 and column2
   ....
   public void addExtraColumnValue(String column, String value) {
     dynamicColumns.put(column, value);
   }

}

动态列由映射器 sql 确定,如下所示:

<select id="queryDynamicColumns" parameterType="java.util.Map"
    resultMap="aResultMap">
         select colum1,colum2, ${dynamicColumns} from table_1
</select>

这个resultMap怎么写?

不知mybatis是否支持mapper配置中的这种映射?( 动态列值将放入地图中。 ) 我没有从官方网站得到一个好的答案,我也尝试了拦截 resultSetHandler 的插件,通过查看 DefaultResultSetHandler 的源代码,它似乎对我的情况没有帮助。

你试过ResultHandler了吗?

问题 MyBatis - ResultHandler is not invoked 可能会有用。

在mybatis 3中,你可以看到方法SqlSession#select(String statement, ResultHandler handler)

您可以在自定义中做任何您想做的事 ResultHandler

如有任何问题,请告诉我。


我想到,如果你从 DefaultResultSetHandler 派生并看这个:

public List<Object> handleResultSets(Statement stmt) throws SQLException {
  final List<Object> multipleResults = new ArrayList<Object>();

  int resultSetCount = 0;
  ResultSetWrapper rsw = getFirstResultSet(stmt);

  List<ResultMap> resultMaps = mappedStatement.getResultMaps();
  int resultMapCount = resultMaps.size();
  validateResultMapsCount(rsw, resultMapCount);
  while (rsw != null && resultMapCount > resultSetCount) {
    ResultMap resultMap = resultMaps.get(resultSetCount);
    handleResultSet(rsw, resultMap, multipleResults, null);
    rsw = getNextResultSet(stmt);
    cleanUpAfterHandlingResultSet();
    resultSetCount++;
  }

  while (rsw != null && resultSetCount < mappedStatement.getResulSets().length) {
    ResultMapping parentMapping = nextResultMaps.get(mappedStatement.getResulSets()[  resultSetCount]);
    if (parentMapping != null) {
      String nestedResultMapId = parentMapping.getNestedResultMapId();
      ResultMap resultMap = configuration.getResultMap(nestedResultMapId);
      handleResultSet(rsw, resultMap, null, parentMapping);
    }
    rsw = getNextResultSet(stmt);
    cleanUpAfterHandlingResultSet();
    resultSetCount++;
  }

  return collapseSingleResultList(multipleResults);
}

你可以更新resultMaps运行时信息,比如更新它的ResultMapping#column然后做动态绑定。那应该行得通!

可以可以做到

1.Whatever 你对 select 动态列的处理是可以的。

2.映射结果: 由于您正在 selecting 来自 table_1 的列(动态)(不会更改),您可以拥有一个 POJO class,其中包含 table_1 中存在的字段,并将其放入在 resultMap.

<select id="queryDynamicColumns" parameterType="java.util.Map"
    resultMap="**Pojo Class With Fields As Columns of table_1**">
         select colum1,colum2, ${dynamicColumns} from table_1
</select>

更新:

如果您的数据库 table 列发生变化而不是尝试使用 JAVA REFLECTION 到动态列

一些肮脏的(?)技巧可以解决您的问题,但您必须从SQL 方面开始。 策略:Select 所有动态列作为一列使用定界符连接列。然后使用相同的分隔符将列拆分为一个数组。

SELECT MANDATORY_COL_1 作为 C1,MANDATORY_COL_2 作为 C2,OPTIONAL_COL_3 || "^" OPTIONAL_COL_4 || "^" OPTIONAL_COL_5 ... AS DYN_COL 来自 TABLE_NAME WHERE ...

现在将第 3 列从字符串拆分为数组是一件简单的事情:DYN_COL.Split("^")

还有几件事: 1) 您可以轻松地将动态列 selection 转换为动态字符串,让您充满活力。 Mybatis 支持 # 命名参数和 $ 动态参数。 2) 如果动态列可能具有不同的数据类型,那么您还需要 select 列的数据类型 - 这将成为上面 SQL 中的第 4 列也是最后一列 3) Columns 数据类型在系统目录的 RDBMS 中可用 - 例如,在 MySQL 中是 INFORMATION_SCHEMA.TABLES 和 INFORMATION_SCHEMA.COLUMNS