zoukankan      html  css  js  c++  java
  • 【Mybatis高级映射】一对一映射、一对多映射、多对多映射

    前言

           当我们学习heribnate的时候,也就是SSH框架的网上商城的时候,我们就学习过它对应的高级映射,一对一映射,一对多映射,多对多映射。对于SSM的Mybatis来说,肯定也是差不多的。既然开了头了,我们就也来简单说一些Mybatis的高级映射。当然说到这些东西的时候,最简单也最常用的就是级联查询,所以我们就以几个简单的级联查询为例,分别说一下Mybatis的一对一、一对多、多对多查询。

    一、一对一映射

    1、需求:

           电商类做买卖,用户提交订单后,某宝根据订单信息和客户的姓名、地址派送,现在查询所有的订单信息,关联查询下但用户信息。

    (1)首先确定执行的sql语句为:

    1. <span style="font-size:18px;">SELECT orders.*,user.username,userss.address FROM orders,user WHEREorders.user_id = user.id</span>  

    resultType方式解决这个问题:

    (1)定义po类:

    1. public class OrdersCustom extends Orders {  //OrdersCustom类继承Orders类后OrdersCustom类包括了Orders类的所有字  
    1. 段,只需要定义用户的信息字段即可。  
    2.    
    3.     private String username;// 用户名称  
    4.     private String address;// 用户地址  
    5.     public String getUsername(){  
    6.                 return username;  
    7.     }  
    8.     public String setUsername(String username){  
    9.                 this.username=username;  
    10.     }  
    11.      ……  
    12. }  

    (2)Mapper映射文件:

    1. <!-- 查询所有订单信息 -->  
    2.     <select id="findOrdersList" resultType="cn.itcast.mybatis.po.OrdersCustom">  
    3.     SELECT  
    4.     orders.*,  
    5.     user.username,  
    6.     user.address  
    7.     FROM  
    8.     orders,    user  
    9.     WHERE orders.user_id = user.id  
    10.     </select>  


    (3)定义mapper接口:

    1. <span style="font-size:18px;">public List<OrdersCustom> findOrdersList() throws Exception;</span>  


    (4)测试:

    1. Public void testfindOrdersList()throws Exception{  
    2.        //获取session  
    3.        SqlSession session = sqlSessionFactory.openSession();  
    4.        //获限mapper接口实例  
    5.        UserMapper userMapper = session.getMapper(UserMapper.class);  
    6.        //查询订单信息  
    7.        List<OrdersCustom> list =userMapper.findOrdersList();  
    8.        System.out.println(list);  
    9.        //关闭session  
    10.        session.close();  
    11.     }  



    使用resultMap解决问题:

    (1)定义resultMap:

    1. <!-- 订单信息resultmap___需要关联查询映射的是用户信息,使用association将用户信息映射到订单对象的用户属性中 -->  
    2. <resultMap type="cn.itcast.mybatis.po.Orders"id="userordermap">  
    3. <!-- 这里的id,是mybatis在进行一对一查询时将user字段映射为user对象时要使用,必须写 -->  
    4. <id property="id" column="id"/>  
    5. <resultpropertyresultproperty="user_id" column="user_id"/>  
    6. <resultpropertyresultproperty="number" column="number"/>  
    7. <associationpropertyassociationproperty="user" javaType="cn.itcast.mybatis.po.User">  
    8. <!-- 这里的id为user的id,如果写上表示给user的id属性赋值 -->  
    9. <id property="id" column="user_id"/>  
    10. <resultpropertyresultproperty="username" column="username"/>  
    11. <resultpropertyresultproperty="address" column="address"/>  
    12. </association>  
    13. </resultMap>  

    (2)调用resultMap:

    1. <select id="findOrdersListResultMap" resultMap="userordermap">  
    2.     SELECT  
    3.     orders.*,  
    4.     user.username,  
    5.     user.address  
    6.     FROM  
    7.     orders,    user  
    8.     WHERE orders.user_id = user.id  
    9. </select>  


    (3)定义mapper接口

    一对一查询总结:

           个人认为啊,这种情况下使用resultType定义输出映射相对简单,因为这样只需要去添加一个po类就行了,按需求添加额外需要的属性,就可以完成映射。而相对于resultType来说,resultMap就显得稍微麻烦一些了,他需要特别定义resultMap来映射相关联表的实体属性。

    二、一对多查询:

    1、需求:

           继上面的需求,查询所有订单信息及订单下的订单明细信息(一个订单信息下面或有很多商品,这个女生买护肤品的时候应该很有感触吧。所以订单信息与订单明细是一对多的关系)

    (1)确定在数据库执行的sql语句:

    1. Select  orders.*, user.username, user.address,orderdetail.idorderdetail_id,orderdetail.items_id,   
    2. orderdetail.items_num FROM orders,user,orderdetail     
    3. WHERE orders.user_id = user.id AND orders.id = orderdetail.orders_id  
     
    执行结果:

    (2)定义po类:

    1. public class Orders{  
    2.     private Integer id;  
    3.     private Integer userId;  
    4.     private String number;  
    5.     private Date createtime;  
    6.     private String note;  
    7.     private User user;  
    8.     private List<OrderDetial> orderDetails;  
    9.     //getter、setter  
    10. }  

    (3)定义resultMap

    1. <!-- 订单信息resultmap -->  
    2. <resultMaptyperesultMaptype="cn.itcast.mybatis.po.Orders"id="userorderdetailmap">  
    3. <id property="id"column="id"/>  
    4. <result property="user_id" column="user_id"/>  
    5. <result property="number" column="number"/>  
    6. <association property="user" javaType="cn.itcast.mybatis.po.User">  
    7. <id property="id" column="user_id"/>  
    8. <result property="username" column="username"/>  
    9. <result property="address" column="address"/>  
    10. </association>  
    11. <collectionpropertycollectionproperty="orderdetails" ofType="cn.itcast.mybatis.po.Orderdetail">  
    12.     <id property="id" column="orderdetail_id"/>  
    13.     <result property="items_id" column="items_id"/>  
    14.     <result property="items_num" column="items_num"/>  
    15. </collection>  
    16. </resultMap>  

           大家可以跟上面对比一下,这两个resultMap除了对订单详细的映射定义外,其他的是完全一样的,现在问题来了,我们需要重新定义上面重复的映射信息吗?答案是不用,resultMap具有可继承特性,我们只需要继承上面的resultMap(userordermap),然后只定义别的就可以了,如下:

    1. <resultMaptyperesultMaptype="cn.itcast.mybatis.po.Orders" id="userorderdetailmap" extends="userordermap">  
    2. <collection property="orderdetails" ofType="cn.itcast.mybatis.po.Orderdetail">  
    3.    <id property="id" column="orderdetail_id"/>  
    4.    <result property="items_id" column="items_id"/>  
    5.    <result property="items_num" column="items_num"/>  
    6. </collection>  
    7. </resultMap>  

    使用extends来继承订单信息resultmap:userordermap

    (4)实现调用:

    1. <selectidselectid="findOrdersDetailList" resultMap="userorderdetailmap">  
    2.     SELECT  
    3.     orders.*,  
    4.     user.username,  
    5.     user.address,  
    6.     orderdetail.id orderdetail_id,  
    7.     orderdetail.items_id,  
    8.     orderdetail.items_num  
    9.     FROM orders,user,orderdetail  
    10.     WHERE orders.user_id = user.id  
    11.     AND orders.id =orderdetail.orders_id  
    12. </select>  

    (5)定义mapper接口:

    1. publicList<Orders>findOrdersDetailList () throws Exception;  


    (6)来测试一下:

    1. Public void testfindOrdersDetailList()throws Exception{  
    2.        //获取session  
    3.        SqlSession session = sqlSessionFactory.openSession();  
    4.        //获限mapper接口实例  
    5.        UserMapper userMapper =session.getMapper(UserMapper.class);  
    6.        //查询订单信息  
    7.        List<Orders> list =userMapper.findOrdersDetailList();  
    8.        System.out.println(list);  
    9.        //关闭session  
    10.        session.close();  
    11.     }  

           这个吧,图没有了,可是可以给大家形容一下,就是返回结果只有四个订单信息,然后每个订单信息里面有两个商品信息list压到这里面。就这样,我们就实现了一对多的查询,为什么这个例子我们不用resultType来执行,其实结果早就给大家了,上面执行sql的结果图,就是返回的信息列表,实际上只有四个订单信息,但是使用resultType会返回8条信息,也就是没有完成去重,还需要我们去手动去重,了然了吗?不是很方便

    三、多对多查询

    (1)需求:

           查询用户购买的商品信息(一个用户可以有N个订单信息,每个订单信息可以有M个商品信息,所以我们需要查询所有的用户信息,关联查询订单及订单明细信息,订单名信息中关联查询商品信息)

    (2)确定要执行的sql:

    1. SELECT  
    2.          orders.*,  
    3.          USER.username,  
    4.          USER.address,  
    5.          orderdetail.idorderdetail_id,  
    6.          orderdetail.items_id,  
    7.          orderdetail.items_num,  
    8.          items.nameitems_name,  
    9.          items.detailitems_detail  
    10. FROM  
    11.          orders,  
    12.          USER,  
    13.          orderdetail,  
    14.          items  
    15. WHERE  
    16.          orders.user_id= USER .id  
    17. AND orders.id = orderdetail.orders_id  
    18. ANDorderdetail.items_id = items.id  

    (3)po类变化:

           在User中添加List<Orders>orders 属性;在Orders类中加入List<Orderdetail> orderdetails属性;Items类,不用动

    (4)定义resultMap:

    1. <resultMap type="cn.itcast.mybatis.po.User"id="userOrderListResultMap">  
    2.        <id column="user_id"property="id"/>  
    3.        <result column="username"property="username"/>  
    4.        <collection property="orders"ofType="cn.itcast.mybatis.po.Orders">  
    5.           <id  column="id"property="id"/>  
    6.           <result property="number" column="number"/>  
    7.           <collection property="orderdetails"ofType="cn.itcast.mybatis.po.Orderdetail">  
    8.                <id  column="orderdetail_id" property="id"/>  
    9.                <result property="ordersId"column="id"/>  
    10.                <result property="itemsId"column="items_id"/>  
    11.                <result property="itemsNum"column="items_num"/>  
    12.                <association property="items"javaType="cn.itcast.mybatis.po.Items">  
    13.                    <id column="items_id" property="id"/>  
    14.                    <result column="items_name" property="name"/>  
    15.                    <result column="items_detail" property="detail"/>  
    16.               </association>  
    17.          </collection>  
    18.      </collection>  
    19. </resultMap>  

    (5)调用resultMap:

    1. <select id="findUserItemResultMap" resultMap="UserItemResultMap" >          
    2.        select orders.*,  
    3.               user.username,  
    4.               user.sex,  
    5.               user.address,  
    6.               orderdetail.id,  
    7.               orderdetail_id,  
    8.               orderdetail.items_id,  
    9.               orderdetail.items_num,  
    10.               orderdetail.orders_id,  
    11.               item.id item_id,  
    12.               item.name item_name,  
    13.               item.detail item_detail,  
    14.               item.price item_price   
    15.        from orders,user,orderdetail,item   
    16.        where orders.user_id=user.id   
    17.             and orders.id=orderdetail.orders_id   
    18.             and orderdetail.items_id=item.id  
    19. </select>  

    到这里,相信大家能看出点端倪来了吧,我们一直都是用<collection></collection>和<association></association>分别对集合和实体进行关联映射,而且它们层层嵌套的方式就跟实体之间层层嵌套的方式一样:user中包含orders,orders中包含orderdetail,orderdetail中包含item。

    (6)然后定义mapper接口:

    1. public interface UserMapper {    List<User> findUserItemResultMap() throws Exception;}  


    结果,就请大家自己去动手实验一下吧!

    到此,我们的Mybatis高级映射之一对一,一对多,多对多映射就分享完了,期间自己又有点收获,总结一下:

    1、resultType:将查询结果按照sql列名pojo属性名一致性映射到pojo中。常见一些明细记录的展示,比如用户购买商品明细,将关联查询信息全部展示在页面时,此时可直接使用resultType将每一条记录映射到pojo中,在前端页面遍历list(list中是pojo)即可。

    2、resultMap:使用association和collection完成一对一和一对多高级映射(对结果有特殊的映射要求)。其中association见关联查询信息映射到一个pojo对象中,collection将关联查询信息映射到一个list集合中然而,使用resultType无法将查询结果映射到pojo对象的pojo属性中,根据对结果集查询遍历的需要选择使用resultType还是resultMap。那就要看我们自己的判断力了。

  • 相关阅读:
    tableView操作数据持久化
    9.0banb以前和9.0以后版本后JSON解析
    数据持久化存储回顾
    解决Xcode会出现的问题
    iview-cli 项目、iView admin 代理与跨域问题解决方案
    将变量做为一个对象的key,push新增进一个数组
    页面加载速度优化的建议
    vue中渲染页面,动态设置颜色
    e.currentTarget与e.target
    iview中tree的事件运用
  • 原文地址:https://www.cnblogs.com/DoubleEggs/p/6243230.html
Copyright © 2011-2022 走看看