Mybatis结果集自动映射的实例代码

网友投稿 298 2023-06-15


Mybatis结果集自动映射的实例代码

在使用Mybatis时,有的时候我们可以不用定义resultMap,而是直接在

1       Mybatis结果集自动映射

在使用Mybatis时,有的时候我们可以不用定义resultMap,而是直接在

1.1     源码分析

关于自动映射这块的逻辑规则可以参考Mybatis的DefaultResultSetHandler的源码,其核心代码如下。

private boolean applyAutomaticMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String columnPrefix) throws SQLException {

List autoMapping = createAutomaticMappings(rsw, resultMap, metaObject, columnPrefix);

boolean foundValues = false;

if (autoMapping.size() > 0) {

for (UnMappedColumAutoMapping mapping : autoMapping) {

final Object value = mapping.typeHandler.getResult(rsw.getResultSet(), mapping.column);

if (value != null || configuration.isCallSettersOnNulls()) {

if (value != null || !mapping.primitive) {

metaObject.setValue(mapping.property, value);

}

foundValues = true;

}

}

}

return foundValues;

}

private List createAutomaticMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String columnPrefix) throws SQLException {

final String mapKey = resultMap.getId() + ":" + columnPrefix;

List autoMapping = autoMappingsCache.get(mapKey);

if (autoMapping == null) {

autoMapping = new ArrayList();

final List unmappedColumnNames = rsw.getUnmappedColumnNames(resultMap, columnPrefix);

for (String columnName : unmappedColumnNames) {

String propertyName = columnName;

if (columnPrefix != null && !columnPrefix.isEmpty()) {

if (columnName.toUpperCase(Locale.ENGLISH).startsWith(columnPrefix)) {

propertyName = columnName.substring(columnPrefix.length());

} else {

continue;

}

}

final String property = metaObject.findProperty(propertyName, configuration.isMapUnderscoreToCamelCase());

if (property != null && metaObject.hasSetter(property)) {

final Class> propertyType = metaObject.getSetterType(property);

if (typeHandlerRegistry.hasTypeHandler(propertyType)) {

final TypeHandler> typeHandler = rsw.getTypeHandler(propertyType, columnName);

autoMapping.add(new UnMappedColumAutoMapping(columnName, property, typeHandler, propertyType.isPrimitive()));

}

}

}

autoMappingsCache.put(mapKey, autoMapping);

}

return autoMapping;

}

在上面的源码中createAutomaticMappings()方法中的下DecVKbMTZ面这句就是获取当前查询结果集中没有在resultMap中映射的字段,以进行自动映射。详情请参考完整的源码。

final List unmappedColumnNames = rsw.getUnmappedColumnNames(resultMap, columnPrefix);

1.2     示例

现假设我们有一个User类,其有id、name、username、email、mobile属性,然后有下面这样一个查询及其对应的resultMap定义。我们可以看到我们查询出来的有id、name、user_name、email和mobile字段,在resultMap中我们只配置了字段user_name对应的是username属性,其它的我们都没配置,但是查询出来的结果中User对象的id、name、username、email和mobile属性都会有值,因为它们会被Mybatis以自动映射策略进行赋值。

select id,name,username user_name,email,mobile from t_user where id=#{id}

1.3     自动映射策略

Mybatis的自动映射策略默认是开启的,而且默认是只对非嵌套的resultMap进行自动映射。这是通过Mybatis的全局配置autoMappingBehavior参数配置的。它一共有三种取值,分别是NONE、PARTIAL和FULL。

l  NONE表示不启用自动映射

l  PARTIAL表示只对非嵌套的resultMap进行自动映射

l  FULL表示对所有的resultMap都进行自动映射

     除了全局的是否启用自动映射的配置外,还可以对特定的resultMap设置是否启用自动映射。这是通过resultMap的autoMapping属性配置的,可选值是true和false。定义在resultMap上的autoMapping的优先级比全局配置的优先级更高。

1.4     resultType自动映射分析

我们在指定一个查询语句的返回结果时,可以直接指定resultType,也可以是指定resultMap,然后由指定的resultMap的type属性指定真实的返回类型。实际上,Mybatis的底层在对结果集进行处理时都是通过resultMap进行处理的。当我们指定的是resultType时,Mybatis内部会生成一个空的resultMap,然后指定其对应的type为我们指定的resultType类型。那这个时候之所以返回结果能自动映射到resultType类型的对应属性上,就是上面介绍的Mybatis的自动映射机制的作用。如果在这种情况下,我们把全局的自动映射关闭了,那么Mybatis就不能自动映射了,也就得不到我们需要的返回结果了。如下就是直接指定的resultType。

select id,name,username,email,mobile from t_user where id=#{id}

Mybatis的mapper.xml文件的内容是由XMLMapperBuilder解析的,而其中定义的Mapper语句(select、insert等)则是由XMLStatementBuilder解析的,解析后会生成一个MappedStatement。对于Select语句,其对应的resultMap的解析的核心逻辑如下,更多信息请参考官方源码。

private List getStatementResultMaps(

String resultMap,

Class> resultType,

String statementId) {

resultMap = applyCurrentNamespace(resultMap, true);

List resultMaps = new ArrayList();

if (resultMap != null) {

String[] resultMapNames = resultMap.split(",");

for (String resultMapName : resultMapNames) {

try {

resultMaps.add(configuration.getResultMap(resultMapName.trim()));

} catch (IllegalArgumentException e) {

throw new IncompleteElementException("Could not find result map " + resultMapName, e);

}

}

} else if (resultType != null) {

ResultMap inlineResultMap = new ResultMap.Builder(

configuration,

statementId + "-Inline",

resultType,

new ArrayList(),

null).build();

resultMaps.add(inlineResultMap);

}

return resultMaps;

}

以上所述是给大家介绍的Mybatis结果集自动映射的实例代码,希望对大家有所帮助,如果大家有任何疑问请给我留言,会及时回复大家的。在此也非常感谢大家对我们网站的支持!


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:spring四种依赖注入方式的详细介绍
下一篇:SpringMVC实现controller中获取session的实例代码
相关文章

 发表评论

暂时没有评论,来抢沙发吧~