MyBatis(五)高级映射

   在关系型数据库中,经常要处理一对一,一对多的关系,在MyBatis中可以轻松解决这种问题,下面我们将分别介绍一对一映射,一对多映射和多对多映射。本文中的映射举例设计四个表:用户表(user),订单表(orders),订单明细表(orderdetail),商品表(items)。

一对一映射

   假设现在有两个表:用户表和订单表,我们可以发现:一个订单只能对应一个用户,则由订单表到用户表是一对一映射的关系。 需求:查询订单相关的订单及用户信息

使用自动映射处理一对一映射

   一个订单对应一个用户,在订单表中添加用户属性:

   使用自动映射就是通过别名使MyBatis自动将值匹配到对应的字段上。根据自动映射的规则,在对应的mapper.xml文件中增加如下方法:

   注意到上述方法中user查询列的别名都是“user.”前缀,通过这种方式将user的属性都映射到了Orders的user属性上。

在接口中添加对应方法:

测试代码如下:

输出日志如下:

   通过日志可以看出,已经查询到一条数据,MyBatis将这条数据映射到两个类中,像这种通过一次查询将结果映射到不同对象的方式,成为关联的嵌套结果映射。这种方式的好处是减少了数据库的查询次数,减轻数据库的压力,缺点是SQL语句较复杂,易出错。 

使用resultMap处理一对一映射

      resultMap的映射思路:使用resultMap将查询结果映射到orders对象在Orders类中添加User属性,将关联查询出来的用户信息映射到orders对象中, resultMap中ID是指定查询列中的唯一标识,如果有多个列组成唯一标识,配置多个id,columns:数据库表中的属性列, property:列所映射到自定义类的标识。

在order对应的xml文件中进行resultMap配置

接口添加方法

测试方法与上面的一致,将方法名改变即可,我们会发现resultMap的写法非常繁琐,MyBatis支持resultMap的映射继承,所以我们可以将resultMap中添加extends继承userMap,修改如下:

使用resultMap的association标签处理一对一映射

 

在order对应的xml文件中进行resultMap配置

<!--使用association关联映射的单个对象-->
<resultMap id="resultOrderUserMap1" type="MavenLG.bean.Orders">
    <id column="id" property="id"/>
    <result column="user_id" property="userId"/>
    <result column="number" property="number"/>
    <result column="createtime" property="createtime" javaType="java.util.Date" jdbcType="TIMESTAMP"/>
    <result column="note" property="note"/>
    <association property="user" columnPrefix="u_" javaType="MavenLG.bean.User">
        <result column="id" property="id"/>
        <result column="address" property="address"/>
        <result column="sex" property="sex"/>
        <result column="username" property="username"/>
    </association>
</resultMap>
<!--resultMap返回-->
<select id="getOrdersByNumber3" parameterType="java.lang.String" resultMap="resultOrderUserMap1">
       select 
       o.*,
       u.id u_id,
       u.address u_address,
       u.sex u_sex,
       u.username u_username 
       from orders o,user u where o.user_id=u.id  and  o.number = #{number};
   </select>

 

接口添加方法getOrdersByNumber3方法。

 使用resultMap提供的association配置一对一关系,配置映射的关联的信息(order表中的user信息)

    association:用于映射关联查询单个的对象的信息

    property:将关联查询映射到对应的自定义对象的属性

    javaType:"全限定名"映射到User的那个属性。

一对多映射

需求:查询用户的订单信息

分析:一个用户存在多个订单,即一对多的关系

主表:user  管理表:orders

select u.*, o.* from user u ,orders o where u.id=o.user_id and u.id=1;

由于查询一个用户可能会出现多个订单,在User类中添加Orders的列表:

在user对应xml文件中使用resultMap提供的Collection配置一对多关系:

  • Collection:对关联查询到的多条记录映射到集合对象中
  • property:将关联查询到的多条记录映射到orders的属性中
  • ofType:指定映射的集合属性中的自定义类型

使用extends继承,不用配置属性信息

<!--一对多映射配置-->
<resultMap id="resultUserOrdersMap" extends="ResultUserMapper" type="MavenLG.bean.User">
    <collection property="orders" columnPrefix="order_" ofType="MavenLG.bean.Orders">
        <result column="id" property="id"/>
        <result column="user_id" property="userId"/>
        <result column="number" property="number"/>
        <result column="createtime" property="createtime" javaType="java.util.Date" jdbcType="TIMESTAMP"/>
        <result column="note" property="note"/>
    </collection>
    <!--<collection property="orders" columnPrefix="order_" resultMap="com.tulun.dao.OrdersMapper1.OrdersResultMap"/>-->
</resultMap>
<sql id="selectId">
   u.id,
   u.username,
   u.sex,
   u.address,
   o.id order_id,
   o.user_id order_user_id,
   o.number order_number,
   o.createtime order_createtime,
   o.note order_note
</sql>
<select id="getUserOrdersByUid" parameterType="int" resultMap="resultUserOrdersMap">
    select
    <include refid="selectId"/>
    from user u ,orders o where u.id=o.user_id and u.id=#{uid};
</select>

多对多映射

查询用户信息,以及它所购买的商品信息  user --》 items

主表:user  从表:orders、orderdetail、items

也就是通过查询某个user,查找到orders,通过orders查找到orderdetail,通过orderdetail查找到items。

一个用户可以有多个订单:

 

一个订单可以拥有多个订单明细:

     

一个订单明细对应一个商品

  

usermapper.xml

 

通过上面配置和sql语句,可以知道,我们写的resultMap看起来好像需要很复杂,其实不然,一步步一层层进行编写,也不难。

 

  如果是一对多关系,那么就使用collection,如果是一对一,那么就使用association,先写user到orders,然后在写orders中的orderdetail,等等,这样一层层嵌套进去,也很明了。

总结:

一 、resultType和resultMap都可以完成高级结果映射,如果没有特殊要求,使用resultType方便

二、resultType和resultMap 的一个主要区别就是要应用场景不同

  resultType主要是查询明细使用;

  resultMap主要是层级查询使用,比如查询用户信息,如何点击查询订单,再去查询订单信息;

  resultMap可以实现延迟加载,而resultType没有该功能;

三、延迟加载就是我们下篇要说的东西,这里就需要注意,resultMap菜可以实现延迟加载,那么什么是延迟加载呢?比如上面一对一关系中,通过orders查询到对应的user,当没有使用到user时,那么orders是不会查询出user的,等当使用user时,才会进行查询加载,这就是延迟加载,也称为懒加载,具体下一节讲解。下一节还会讲解一级缓存,二级缓存的问题。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值