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结果集自动映射的实例代码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

(0)

相关推荐

  • MyBatis中多对多关系的映射和查询

    先说一下需求: 在页面上显示数据库中的所有图书,显示图书的同时,显示出该图书所属的类别(这里一本书可能同时属于多个类别) 创建表: 笔者这里使用中间表连接图书表和图书类别表,图书表中没有使用外键关联图书类别表 而是在中间表中引用了图书主键和类别主键 通过中间表来 表示 图书 和 图书类别 的关系 建立图书表(图书编号,图书名字) create table book ( bid int primary key auto_increment, bname varchar(20) ); 建立类别表(类

  • Mybatis中实体类属性与数据列表间映射方法介绍

    Mybatis不像Hibernate中那么自动化,通过@Column注解或者直接使用实体类的属性名作为数据列名,而是需要自己指定实体类属性和 数据表中列名之间的映射关系,这一点让用惯了Hibernate的人很不习惯,所幸经过探索找到了建立映射关系的三种办法,其中总也有比较 简单的. 首先先定义一个实体类,如下: public class User implements Serializable { private Integer userId; private String userName;

  • Mybatis实体类和表映射问题(推荐)

    本文是小编给大家带来的mybatis中实体类和表映射问题的知识,学习本教程能够快速帮助我们解决字段名与实体类属性名不相同的冲突问题,需要的朋友一起看看吧! 一.准备演示需要使用的表和数据 CREATE TABLE orders( order_id INT PRIMARY KEY AUTO_INCREMENT, order_no VARCHAR(20), order_price FLOAT ); INSERT INTO orders(order_no, order_price) VALUES('a

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

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

  • Automapper实现自动映射的实例代码

    出于安全考虑,在后台与前台进行数据传输时,往往不会直接传输实体模型,而是使用Dto(Data transfer object 数据传输对象),这样在后台往前台传递数据时可以省略不必要的信息,只保留必要的信息,大大增强数据安全性. 下面给出两个相互对应的关系模型User.UserDto public class User { private const int NameMaxLength = 20; private const int PassWordMaxLength = 16; [Key] p

  • SpringBoot+MyBatis简单数据访问应用的实例代码

    因为实习用的是MyBatis框架,所以写一篇关于SpringBoot整合MyBatis框架的总结. 一,Pom文件 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:

  • Mybatis查询记录条数的实例代码

    这几天在学SSM框架,今天在SSM框架中根据某个条件查询MySQL数据库中的记录条数,碰到一些问题,记录一下 User.xml <select id="userNameValidate" parameterType="String" resultType="Integer"> select count(*) from user where username like #{value} </select> <selec

  • iOS UIScrollView滚动视图/无限循环滚动/自动滚动的实例代码

    我们都知道UIScrollView有一种很流畅的切换效果,结合UIPageControl的辅助展示效果,就可以完成一个很不错的产品介绍功能页面.下面给大家分享iOS UIScrollView滚动视图/无限循环滚动/自动滚动功能,具体代码如下所示: <UIScrollViewDelegate> #define WIDTH [[UIScreen mainScreen] bounds].size.width #define HEIGHT [[UIScreen mainScreen] bounds].

  • c语言同名标靶点自动匹配算法实现实例代码

    1.两个标靶数据 2.匹配结果 3.代码 #include <iostream> #include <vector> #include <math.h> using namespace std; struct Point { int id; float x,y,z; Point(int _id,float _x,float _y,float _z):id(_id),x(_x),y(_y),z(_z){} }; struct Triangle { Point p1,p2,

  • C# 模拟浏览器并自动操作的实例代码

    本文主要讲解通过WebBrowser控件打开浏览页面,并操作页面元素实现自动搜索功能,仅供学习分享使用,如有不足之处,还请指正. 涉及知识点 WebBrowser:用于在WinForm窗体中,模拟浏览器,打开并导航网页. HtmlDocument:表示一个Html文档的页面.每次加载都会是一个全新的页面. GetElementById(string id):通过ID或Name获取一个Html中的元素. HtmlElement:表示一个Html标签元素. BackgroundWorker 后台执行

  • Android实现图片自动切换功能(实例代码详解)

    在Android中图片的自动切换不仅可以实现自动切换,而且还可以使用手动切换.而且一般在切换的时候,在图片下方还带有其他内容的切换,用来标记是第几个图片的切换. 这种效果在我们日常生活中很常见,例如某宝购物,一些商城都可以使用到,用户体验度极好,今天小编就通过实例代码给大家分享android 图片自动切换功能的实现. 实现效果如下: 具体的示例代码如下: 布局代码: <?xml version="1.0" encoding="utf-8"?> <S

  • Mybatis注解增删改查的实例代码

    要点 有另一种方法来完成语句映射. 它们映射的语句可以不用 XML 来配置,而可以使用 Java 注解来配置. 使用注解来映射简单语句会使代码显得更加简洁,但对于稍微复杂一点的语句,Java 注解不仅力不从心,还会让你本就复杂的 SQL 语句更加混乱不堪. 如果你需要做一些很复杂的操作,最好用 XML 来映射语句. 需要在config.xml中注册Java接口 <mappers> <mapper class="com.mybatis.DAO.PeopleMapper"

  • iOS实现输入框跟随键盘自动上移的实例代码

    场景还原 有些时候在包含输入框的页面中,点击输入框输入会因键盘弹起而遮挡住一部分输入框,影响用户体验.iOS在默认情况下并不会处理这种问题,不过我们可以自己实现键盘弹起输入框自动上移的效果. 实现思路 观察键盘的弹起与收回,当弹起的键盘会遮挡住输入框时,将输入框跟随键盘一并上移合适的距离,当键盘收回时,输入框回到原始状态. 具体方案 1. 注册两个观察者,观察键盘的弹起与收回 [[NSNotificationCenter defaultCenter] addObserver:self selec

随机推荐