mybatis联合查询

一、 一对一 resultType实现

  1. 通过扩展类来实现:

    • 复杂查询时,表单对应的po类已不能满足输出结果集的映射。所以要根据需求建立一个扩展类来作为resultType的类型。这个扩展类是一个继承实体类,然后在这个扩展类中再写入别的表的一些字段作为属性,实现连表查询的结果可以封装入一个类中。
    1. 步骤
      1. 建立扩展类
        package com.Marsoft.model;
        
        public class OrdersExt extends Orders {
            private String username;
            private String address;
        
            public String getUsername() {
                return username;
            }
        
            public void setUsername(String username) {
                this.username = username;
            }
        
            public String getAddress() {
                return address;
            }
        
            public void setAddress(String address) {
                this.address = address;
            }
        
            @Override
            public String toString() {
                return "OrdersExt{" +
                        "username='" + username + '\'' +
                        ", address='" + address + '\'' +
                        '}' + super.toString();
            }
        }
        
      2. 编写接口中的方法
        package com.Marsoft.mapper;
        
        import com.Marsoft.model.OrdersExt;
        
        public interface OrderMapper {
        
            public OrdersExt findOrderById(int id);
        
        }
        
      3. 定义一个映射文件
        <?xml version="1.0" encoding="UTF-8" ?>
        <!DOCTYPE mapper
                PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
                "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
        <mapper namespace="com.Marsoft.mapper.OrderMapper">
        
            <select id="findOrderById" parameterType="int" resultType="ordersExt">
                SELECT
                  o.*,u.`username`,u.`address`
                FROM
                  orders o,USER u
                WHERE o.`user_id` = u.`id` AND o.`id` = #{id};
            </select>
        
        </mapper>
        
      4. 方法实现
        /**
         * 一对一:写个订单类的扩展
         */
        @Test
        public void test6() {
            OrderMapper mapper = session.getMapper(OrderMapper.class);
        
            OrdersExt ordersExt = mapper.findOrderById(3);
        
            System.out.println(ordersExt);
        }
        

    报错:

    • org.apache.ibatis.binding.BindingException: Type interface com.Marsoft.mapper.OrderMapper is not known to the MapperRegistry.
      • 这个报错是因为在SQLMapConfig文件中没有配置对应的mapper接口
    • org.apache.ibatis.binding.BindingException: Invalid bound statement (not fou
      • 这个报错的原因是:select标签的id写错了
  2. 模型里有模型

    • 步骤:
      1. 首先还是在接口中创建一个方法
        public Orders findOrderById2(int id);
        
      2. 然后在配置文件中进行配置
        <!--如果模型里有模型,使用resultMap-->
        <resultMap id="ordersRslMap" type="orders">
            <!--往orders的模型里匹配数据-->
            <id column="id" property="id"></id>
            <id column="note" property="note"></id>
            <id column="number" property="number"></id>
            <id column="createtTime" property="createtTime"></id>
        
            <!--往orders的user匹配数据-->
            <association property="user" javaType="user">
                <!--在这里,JavaType的属性值代表的是具体的某个类-->
                <id column="user_id" property="id"></id>
                <id column="username" property="username"></id>
                <id column="address" property="address"></id>
            </association>
        </resultMap>
        
        <select id="findOrderById2" parameterType="int" resultMap="ordersRslMap">
            SELECT
              o.*,u.`username`,u.`address`
            FROM
              orders o,USER u
            WHERE
              o.`user_id` = u.`id`
            AND
              o.`id` = #{id};
        </select>
        
        • id标签中column属性和property属性中的值要与实体类中的属性要严格一一对应,其中包括大小写也要对应。
      3. 最后在测试类中进行方法的实现。
        /**
         * 一对一:模型里有模型
         */
        @Test
        public void test7() {
            OrderMapper mapper = session.getMapper(OrderMapper.class);
        
            Orders order = mapper.findOrderById2(3);
            System.out.println(order);
            System.out.println(order.getUser());
        }
        
  • 注意:如果模型里有模型,那么select标签就用resultMap属性,而不是用resultType属性

二、一对多实现

  1. 一对多实现【模型里有集合】
    • 需求:根据订单ID查找订单信息和订单明细
    • 在这里出现一对多,一对多就需要在原有的类中加入集合属性,集合属性用于一对多的实现。
      *步骤
      1. 首先是在实体类中加入多对应的那个类的集合。
        /*一对多数据封装*/
        private List<OrderDetail> orderDetails;
        
        public List<OrderDetail> getOrderDetails() {
            return orderDetails;
        }
        
        public void setOrderDetails(List<OrderDetail> orderDetails) {
            this.orderDetails = orderDetails;
        }
        
      2. 然后在OrderMapper.xml文件中进行映射配置。
        <resultMap id="orderRslMap3" type="orders">
            <!--往orders模型匹配数据-->
            <id column="id" property="id"></id>
            <id column="note" property="note"></id>
            <id column="number" property="number"></id>
            <id column="createTime" property="createTime"></id>
        
            <!--往orders的user匹配数据
            模型里有模型,使用association来配置-->
            <association property="user" javaType="user">
                <id column="user_id" property="id"></id>
                <id column="username" property="username"></id>
                <id column="address" property="address"></id>
            </association>
        
            <!--一对多匹配:往orders的orderdetails匹配数据
            注意:集合里类型使用ofType,而不JavaType-->
            <collection property="orderDetails" ofType="orderDetail">
                <id column="detail_id" property="id"></id>
                <id column="items_id" property="itemsId"></id>
                <id column="items_num" property="itemsNum"></id>
            </collection>
        </resultMap>
        
        <select id="findOrderById3" parameterType="int" resultMap="orderRslMap3">
            SELECT
                o.*,
                u.`username`,
                u.`address`,
                od.`id` detail_id,
                od.`items_id`,
                od.`items_num`
            FROM
                orders o,
                USER u,
                `orderdetail` od
            WHERE
                o.`user_id` = u.`id`
                AND o.`id` = od.`orders_id`
                AND o.`id` = #{id};
        </select>
        
        • 在一个类中不仅包含这个类本身的属性,还包括一个集合,和一个其他类作为此类的属性,所以想要将这些东西尽数装入该类中,需要resultMap标签,以及他的子标签id表和association标签,以及collection标签。
      3. 在对应的接口中写方法
        public Orders findOrderById3(int id);
        
      4. 在测试类中实现
        /**
         * 一对多
         */
        @Test
        public void test8 () {
            OrderMapper mapper = session.getMapper(OrderMapper.class);
        
            Orders order = mapper.findOrderById3(3);
            System.out.println(order);
            System.out.println(order.getUser());
            System.out.println(order.getOrderDetails());
        }
        

三、多对多的实现

  • 需求:根据订单ID查找订单信息、用户信息和订单明细信息

image.png

  • 在user类型的集合中有一个Orders类型的集合,在order模型中又有OrderDetail的集合,在OrderDetail里面又有Items模型,就这样一环扣一环。
  • 实现步骤:
    1. 在接口中写方法
      /**
       * 多对多实现
       * 查询用户信息以及用户购买的商品信息
       * @return
       */
      public List<User> findUserAndOrderInfo();
      
    2. 在实体类中加入多对多所需要的各种集合和模型
      • 比如:
        package com.Marsoft.model;
        
        import java.util.Date;
        import java.util.List;
        
        public class Orders {
            private Integer id;
            private String number;
            private Date createTime;
            private String note;
        
            private User user;
        
            /*一对多数据封装*/
            private List<OrderDetail> orderDetails;
        
            public List<OrderDetail> getOrderDetails() {
                return orderDetails;
            }
        
            public void setOrderDetails(List<OrderDetail> orderDetails) {
                this.orderDetails = orderDetails;
            }
        
            public User getUser() {
                return user;
            }
        
            public void setUser(User user) {
                this.user = user;
            }
        
            public Integer getId() {
                return id;
            }
        
            public void setId(Integer id) {
                this.id = id;
            }
        
            public String getNumber() {
                return number;
            }
        
            public void   setNumber(String number) {
                this.number = number;
            }
        
            public Date getCreateTime() {
                return createTime;
            }
        
            public void setCreateTime(Date createTime) {
                this.createTime = createTime;
            }
        
            public String getNote() {
                return note;
            }
        
            public void setNote(String note) {
                this.note = note;
            }
        
            @Override
            public String  toString() {
                return "Orders{" +
                        "id=" + id +
                        ", number='" + number + '\'' +
                        ", createTime=" + createTime +
                        ", note='" + note + '\'' +
                        '}';
            }
        }
        
    3. 在映射文件中写具体的SQL语句以及传出方式
      <!--通过多对多实现
      查询用户信息及用户购买的商品信息-->
      <resultMap id="userRslMap" type="user">
          <!--1.匹配user属性-->
          <id column="id" property="id"></id>
          <result column="username" property="username" />
          <result column="address" property="address" />
      
          <!--2.匹配user的orderList-->
          <collection property="ordersList" ofType="orders">
              <id column="order_id" property="id"></id>
              <result column="number" property="number" />
              <result column="createtime" property="createTime" />
              <result column="note" property="note" />
      
              <!--3.匹配Orders里有OrderDetails-->
              <collection property="orderDetails" ofType="orderDetail">
                  <id column="detail_id" property="id"></id>
                  <result column="items_id" property="itemsId"/>
                  <result column="items_num" property="itemsNum"/>
      
                  <!--4.配置订单详情的商品-->
                  <association property="items" javaType="items">
                      <id column="items_id" property="id"></id>
                      <result column="name" property="name"/>
                      <result column="price" property="price"/>
                      <result column="detail" property="detail"/>
                  </association>
              </collection>
          </collection>
      </resultMap>
      
      <select id="findUserAndOrderInfo" resultMap="userRslMap">
          SELECT
              u.`id`,
              u.`username`,
              u.`address`,
              o.`id` order_id,
              o.`number`,
              o.`createtime`,
              o.`note`,
              od.`id` detail_id,
              od.`items_id`,
              od.`items_num`,
              it.`name`,
              it.`price`,
              it.`detail`
          FROM
              USER u,
              orders o,
              `orderdetail` od,
              items it
          WHERE
              o.`user_id` = u.`id`
              AND o.`id` = od.`orders_id`
              AND od.`items_id` = it.`id`;
      </select>
      
    4. 在测试类中实现具体的操作。
      /**
       * 多对多
       * 查询用户和商品信息
       */
      @Test
      public void test9 () {
          UserMapper mapper = session.getMapper(UserMapper.class);
      
          List<User> users = mapper.findUserAndOrderInfo();
          for (User user : users) {
              System.out.println("用户信息:"+user);
      
              for (Orders orders : user.getOrdersList()) {
                  System.out.println("订单信息:"+orders);
                  System.out.println("订单详情");
      
                  for (OrderDetail od : orders.getOrderDetails()) {
                      System.out.println(od+":"+od.getItems());
                  }
                  System.out.println("-----------------------------------");
              }
      
          }
      }
      

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值