Mybatis强大的映射器ResultMap

ResultMap在Mybatis中用于处理复杂查询结果,如一对一、一对多关系。通过自动映射和配置,能简化处理结果集的代码。文章介绍了如何高效使用ResultMap,包括自动驼峰命名转换、配置自动映射、定义一对一和一对多关系,以及解决字段冲突问题。并提到了N+1问题的解决方案和官方文档链接。
  • ResultMap是什么,有什么样的魔力
    • 在使用Mybatis做查询时,通常返回的结果集,我们会使用一个POJO来直接接收,但是复杂的SQL,尤其多表联合,返回一对一,一对多等关系数据时,ResultMap就能发挥作用了。
    • 配合自动关系映射,处理复杂结果集就变得简单许多,能让我们省去大量处理结果集的代码
  • 如何高效使用
    • 为了尽可能的少写Java类中属性和数据库中列的映射关系,首先我们的数据字段设计要规范(能够让Mybatis自动驼峰命名转换识别),然后Mybatis配置文件开启选项。这样数据库字段比如user_name会自动映射类中userName属性
      • <setting name="mapUnderscoreToCamelCase" value="true" />
    • 在xxxMapper.xml文件中定义ResultMap
    • 我使用一个1:N的例子来说明如何使用。现在又User,Address两个类,通过userId来关联,一个人有多个地址。我要查出某个人的信息以及他所有的地址。
    • import java.util.List;
      
      public class User {
      
      	private String userId;
      	private String userName;
      	private Integer flag;
      	private List<Address> addressList;
      	public String getUserId() {
      		return userId;
      	}
      	public void setUserId(String userId) {
      		this.userId = userId;
      	}
      	public String getUserName() {
      		return userName;
      	}
      	public void setUserName(String userName) {
      		this.userName = userName;
      	}
      	public Integer getFlag() {
      		return flag;
      	}
      	public void setFlag(Integer flag) {
      		this.flag = flag;
      	}
      	public List<Address> getAddressList() {
      		return addressList;
      	}
      	public void setAddressList(List<Address> addressList) {
      		this.addressList = addressList;
      	}
      	
      	
      }
      
      
      public class Address {
      
      	private String addressId;
      	private Integer province;
      	private Integer city;
      	private Integer flag;
      	private String userId;
      	
      	public String getUserId() {
      		return userId;
      	}
      	public void setUserId(String userId) {
      		this.userId = userId;
      	}
      	public String getAddressId() {
      		return addressId;
      	}
      	public void setAddressId(String addressId) {
      		this.addressId = addressId;
      	}
      	public Integer getProvince() {
      		return province;
      	}
      	public void setProvince(Integer province) {
      		this.province = province;
      	}
      	public Integer getCity() {
      		return city;
      	}
      	public void setCity(Integer city) {
      		this.city = city;
      	}
      	public Integer getFlag() {
      		return flag;
      	}
      	public void setFlag(Integer flag) {
      		this.flag = flag;
      	}
      	
      	
      }
      

       

    • 假定有一个UserMapper.xml。在里面写一个查询,并取出上面要求的结果集:

      <select id="queryUserInfoByUserId" resultMap="userAddressMap">
          select a.*,b.address_id ad_address_id,b.province ad_province,b.city ad_city,b.flag ad_flag from tb_user a inner join tb_address b
          on a.user_id = b.user_id where a.user_id = #{userId,jdbcType=VARCHAR}
      </select>
      
      <resultMap type="com.loo.User" id="userAddressMap" autoMapping="true">
              <id column="user_id" property="userId" jdbcType="VARCHAR" />
      	<collection property="addressList" ofType="com.loo.Address" columnPrefix="ad_" autoMapping="true">
      	    <id property="addressId" column="address_id"/>
      	</collection>
      </resultMap>

      上面这个配置文件中,有几个地方要注意。autoMapping=true  表示自动映射数据库字段和类属性关系,因为我们的命名都是规范的,没必要逐个去定义字段属性关系。<collection>就是表示一对多中的多,同理当中也有autoMapping=true。ofType表示集合中装的具体类型。columnPrefix="ad_" 这一段主要是对子表列名做了别名加前缀,原因是User类和Address类中都有一个叫flag的属性,我们使用别名加前缀的形式,就可以让Mybatis解析的时候,知道具体对应哪个类中的flag。也就是说如果你的多个类中没有重复的字段列,那么你可以不必要这个配置,如果有而且要获取到结果集中,那就需要加上。

    • <id property="" column="" />这个标签的主要目的是告诉mybatis解析数据的时候可以使用当前列作为键来关联类之间的关系。按照官方说法,即使你不去配置这个属性,结果集也可以正确解析,但最好设置,因为这个提升性能(解析的时候明确的知道对应关系,而不需要Mybatis通过sql中的关联反推)

    • 当mybatis装载完毕,各项基于xml的配置和mapper文件中的映射关系已经加载到Configuration之中,当查询触发的时候

      boolean org.apache.ibatis.executor.resultset.DefaultResultSetHandler.applyAutomaticMappings(ResultSetWrapper rsw, ResultMap resultMap, MetaObject metaObject, String columnPrefix) throws SQLException 方法解析结果集的时候会用到String org.apache.ibatis.reflection.MetaObject.findProperty(String propName, boolean useCamelCaseMapping)去查找对应关系。对应实现有BeanWarpper,MapWarpper

       

  • 其他1:1,N:N的关系查询,大多都类似。当然也各有个的瑕疵,以及解决办法。比如N+1问题,使用延时加载,或者两次结果集查询联立等解决N+1等

  • 官网对于ResultMap的使用说明:https://mybatis.org/mybatis-3/zh/sqlmap-xml.html#Result_Maps

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值