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
我有一个要求,可能有点复杂。想想我有豆 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