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

 更新时间:2017年02月06日 16:59:53   投稿:mrr  
在使用Mybatis时,有的时候我们可以不用定义resultMap,而是直接在<select>语句上指定resultType。这个时候其实就用到了Mybatis的结果集自动映射,下面通过本文给大家分享Mybatis结果集自动映射的实例代码,一起看看吧

在使用Mybatis时,有的时候我们可以不用定义resultMap,而是直接在<select>语句上指定resultType。这个时候其实就用到了Mybatis的结果集自动映射。Mybatis的自动映射默认是开启的,有需要我们也可以将其关闭(还可以调整自动映射的策略)。

1       Mybatis结果集自动映射 

       在使用Mybatis时,有的时候我们可以不用定义resultMap,而是直接在<select>语句上指定resultType。这个时候其实就用到了Mybatis的结果集自动映射。Mybatis的自动映射默认是开启的,其在映射的时候会先把没有在resultMap中定义字段映射的字段按照名称相同的方式自动映射到返回类型的对应属性上。自动映射的时候会忽略大小写,比如查询语句中查询出来了一个字段是ID,我们对应的返回类型有一个属性id,且有一个setId()方法,那么id跟ID也是可以匹配的,是可以自动映射的,Mybatis就会把查询出来的结果集中字段ID对应的值赋给返回类型对象的id属性。

1.1     源码分析

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

private boolean applyAutomaticMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String columnPrefix) throws SQLException {
  List<UnMappedColumAutoMapping> 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<UnMappedColumAutoMapping> createAutomaticMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String columnPrefix) throws SQLException {
  final String mapKey = resultMap.getId() + ":" + columnPrefix;
  List<UnMappedColumAutoMapping> autoMapping = autoMappingsCache.get(mapKey);
  if (autoMapping == null) {
   autoMapping = new ArrayList<UnMappedColumAutoMapping>();
   final List<String> 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()方法中的下面这句就是获取当前查询结果集中没有在resultMap中映射的字段,以进行自动映射。详情请参考完整的源码。

 final List<String> 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以自动映射策略进行赋值。

 <resultMap type="com.elim.learn.mybatis.model.User" id="BaseResult">
   <result column="user_name" property="username"/>
  </resultMap>
  <select id="findById" resultMap="BaseResult" parameterType="java.lang.Long" >
   select id,name,username user_name,email,mobile from t_user where id=#{id}
  </select>

1.3     自动映射策略

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

l  NONE表示不启用自动映射

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

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

    <!-- 自动映射类型,可选值为NONE、PARTIAL和FULL,参考AutoMappingBehavior枚举 -->
   <setting name="autoMappingBehavior" value="PARTIAL"/>

       除了全局的是否启用自动映射的配置外,还可以对特定的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="findById" resultType="com.elim.learn.mybatis.model.User" parameterType="java.lang.Long" >
   select id,name,username,email,mobile from t_user where id=#{id}
  </select>

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

private List<ResultMap> getStatementResultMaps(
   String resultMap,
   Class<?> resultType,
   String statementId) {
  resultMap = applyCurrentNamespace(resultMap, true);
  List<ResultMap> resultMaps = new ArrayList<ResultMap>();
  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<ResultMapping>(),
     null).build();
   resultMaps.add(inlineResultMap);
  }
  return resultMaps;
 }

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

相关文章

  • Java实现图片上传至FastDFS入门教程

    Java实现图片上传至FastDFS入门教程

    这篇文章主要介绍了Java实现图片上传至FastDFS入门教程,通过前端ajax提交图片到后端,java处理服务器文件上传至FastDFS文件服务器系统,以下就是详细内容,需要的朋友可以参考下
    2021-07-07
  • Windows下使用Graalvm将Springboot应用编译成exe大大提高启动和运行效率(推荐)

    Windows下使用Graalvm将Springboot应用编译成exe大大提高启动和运行效率(推荐)

    这篇文章主要介绍了Windows下使用Graalvm将Springboot应用编译成exe大大提高启动和运行效率,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-02-02
  • 使用jekins自动构建部署java maven项目的方法步骤

    使用jekins自动构建部署java maven项目的方法步骤

    这篇文章主要介绍了使用jekins自动构建部署java maven项目的方法步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01
  • 使用GSON库将Java中的map键值对应结构对象转换为JSON

    使用GSON库将Java中的map键值对应结构对象转换为JSON

    GSON是由Google开发并开源的实现Java对象与JSON之间相互转换功能的类库,这里我们来看一下使用GSON库将Java中的map键值对应结构对象转换为JSON的示例:
    2016-06-06
  • java实现简单五子棋小游戏(1)

    java实现简单五子棋小游戏(1)

    这篇文章主要为大家详细介绍了java实现简单五子棋小游戏的第一部分,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01
  • Java常用工具类汇总 附示例代码

    Java常用工具类汇总 附示例代码

    这篇文章主要介绍了Java常用工具类,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着我来一起学习学习吧,希望能给你带来帮助
    2021-06-06
  • Java8如何基于flatMap处理异常函数

    Java8如何基于flatMap处理异常函数

    这篇文章主要介绍了Java8如何基于flatMap处理异常函数,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-09-09
  • SpringBoot实现短信发送及手机验证码登录

    SpringBoot实现短信发送及手机验证码登录

    本文主要介绍了SpringBoot实现短信发送及手机验证码登录,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-07-07
  • Java8流式API将实体类列表转换为视图对象列表的示例

    Java8流式API将实体类列表转换为视图对象列表的示例

    这篇文章主要介绍了Java8流式API将实体类列表转换为视图对象列表的示例,文中有相关的代码示例供大家参考,对大家的学习或工作有一定的帮助,需要的朋友可以参考下
    2024-11-11
  • SpringBoot中的自定义starter

    SpringBoot中的自定义starter

    这篇文章主要介绍了SpringBoot中的自定义starter,Starter是Spring Boot中的一个非常重要的概念,Starter相当于模块,它能将模块所需的依赖整合起来并对模块内的Bean根据环境(条件)进行自动配置,需要的朋友可以参考下
    2024-01-01

最新评论