美文网首页
(6)联合查询

(6)联合查询

作者: Mrsunup | 来源:发表于2018-10-28 21:36 被阅读0次

1.嵌套结果

这里先展示一对多的例子,一对一的例子暂时不展示了,区别一对多的关联查询使用collection进行映射,一对一的关联查询使用了association来进行映射,区别不大

展示的例子如下:一个用户有多个订单,查询出所有的用户的,并把用户的关联的订单也打印处理

  • 用户User的实体类(省略get和set方法)
public class User {
    private Integer id;

    private String username;

    private Date birthday;

    private String sex;

    private String address;

    //用户创建的订单列表
    private List<Orders> orderList;
 @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", birthday=" + birthday +
                ", sex='" + sex + '\'' +
                ", address='" + address + '\'' +
                ", orderList=" + orderList +
                '}';
    }
}
  • 订单类Orders的实体类(省略get和set方法)
public class Orders {
   private Integer id;

   private Integer userId;

   private String number;

   private Date createtime;

   private String note;
}
  • 对应的UserMapper的方法
public interface UserMapper {
    //通过user来关联订单号
    List<User>  findOrdersByUser();
} 
  • 对应的UserMapper.xml的接口的内容
 <!-- 查询用户所在的订单号,一个用户对应多个订单号-->
  <select id="findOrdersByUser" parameterType="com.mybatis.project.po.User" resultMap="findOrdersByUserMap">
          select  users.*,
                            orders.id orders_id,
                            orders.createtime,
                            orders.note,
                            orders.number
                from orders , user  users
      where orders.user_id = users.id ;
  </select>

  <resultMap id="findOrdersByUserMap" type="com.mybatis.project.po.User">
    <id property="id" column="id"/>
    <result property="username" column="username"/>
    <result property="sex" column="sex"/>
    <result property="birthday" column="birthday"/>
    <result property="address" column="address"/>
    <collection property="orderList" ofType="com.mybatis.project.po.Orders">
        <id property="id" column="orders_id"/>
        <result property="userId" column="id"/>
        <result property="number" column="number"/>
        <result property="createtime" column="createtime"/>
        <result property="note" column="note"/>
    </collection>
  </resultMap>
  • 具体测试类

    //嵌套结果   一对多
    @Test
    public void nestedResultTest(){
        SqlSession sqlSession  =sqlSessionFactory.openSession();
        //创建userMapper对象,mybatis自动生成mapper代理对象
        UserMapper userMapper =  sqlSession.getMapper(UserMapper.class);

        List<User> list = userMapper.findOrdersByUser();

        System.out.println(list);
    }
  • 输出结果 :可以发现用户id为1的有两个订单,用户id为2的有一个订单,如果是直接查询原有的sql语句,发现了有三条记录,mybatis对user的信息相同的记录进行了合并
[User{id=1, username='sunkang', birthday=Sun Oct 07 00:00:00 CST 2018, sex='1', address='杭州:update:update:update:update:update', orderList=[com.mybatis.project.po.Orders@6cc7b4de, com.mybatis.project.po.Orders@32cf48b7]},
 User{id=2, username='陈王五', birthday=Sun Oct 07 00:00:00 CST 2018, sex='1', address='北京:update:update:update:update', orderList=[com.mybatis.project.po.Orders@679b62af]}]
  • 更加完整的例子
    参考github的项目mybatis下的mybatis-generator工程下的com.mybatis.bestPractice.nested

地址为: https://github.com/sunkang123/mybatis

2.嵌套查询

嵌套查询可以实现延迟加载,有效的避免了n+1的问题,只是根据需要的时候才把关联的数据查询出来

  • 开启延迟加载的配置

如果要实现延迟加载需要在mybatis的配置文件上配置:

   <settings>
        <!--lazyLoadingEnabled  延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。 特定关联关系中可通过设置fetchType属性来覆盖该项的开关状态。-->
        <setting name="lazyLoadingEnabled" value="true"/>
        <!--    aggressiveLazyLoading当开启时,任何方法的调用都会加载该对象的所有属性。否则,每个属性会按需加载(参考lazyLoadTriggerMethods).-->
        <setting name="aggressiveLazyLoading" value="false"/>
    </settings>

·

  • 编写对应的mapper接口
    //嵌套查询,可以实现延迟加载,避免了n+1问题
    List<User>   findOrdersByUserLazy();
  • 编写mapper的文件
  <!--通过延迟加载  只需要查询所需要的数据-->

  <select id = "findOrdersByUserLazy" parameterType="com.mybatis.project.po.User" resultMap="findOrdersByUserLazyMap" >
     select *  from user
  </select>
  <resultMap id="findOrdersByUserLazyMap" type="com.mybatis.project.po.User" >
    <id property="id" column="id"/>
    <result property="username" column="username"/>
    <result property="sex" column="sex"/>
    <result property="birthday" column="birthday"/>
    <result property="address" column="address"/>
    <!--select 表示查询的sql语句,column表示关联查询的参数-->
    <collection property="orderList" ofType="com.mybatis.project.po.Orders"  select="findOrdersById" column="id"/>
  </resultMap>

  <select id="findOrdersById" resultType="com.mybatis.project.po.Orders" parameterType="int" >
    select * from orders   where user_id =#{id}
  </select>
  • 编写测试类
 //嵌套结果查询 ,可以设置延迟加载,来达到延迟加载的效果
    @Test
    public void nestedQuery() throws InterruptedException {
        SqlSession sqlSession  =sqlSessionFactory.openSession();
        //创建userMapper对象,mybatis自动生成mapper代理对象
        UserMapper userMapper =  sqlSession.getMapper(UserMapper.class);

        //这里是1次
        List<User> list = userMapper.findOrdersByUserLazy();
        System.out.println(list.get(0).getBirthday());

        Thread.sleep(5000);
        System.out.println("----------");
        //当要使用的时候他们再去拉取数据 这里就是N次
        System.out.println(list.get(0).getOrderList().get(0).getId());
        System.out.println(list.get(1).getOrderList().get(0).getId());
        //1次 + N次问题
    }
  • 输出结果如下: 可以发现先输出select * from user 这个语句,当加载具体的orders的内容时才输出select * from orders where user_id =?,说明已经达到了延迟的加载的目的
DEBUG [main] - Created connection 1370651081.
DEBUG [main] - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@51b279c9]
DEBUG [main] - ==>  Preparing: select * from user 
DEBUG [main] - ==> Parameters: 
DEBUG [main] - <==      Total: 5
Sun Oct 07 00:00:00 CST 2018
----------
DEBUG [main] - ==>  Preparing: select * from orders where user_id =? 
DEBUG [main] - ==> Parameters: 1(Integer)
DEBUG [main] - <==      Total: 2
1
DEBUG [main] - ==>  Preparing: select * from orders where user_id =? 
DEBUG [main] - ==> Parameters: 2(Integer)
DEBUG [main] - <==      Total: 1
3

总结: 嵌套结果和嵌套查询的区别在于嵌套结果需要一次性把所有的记录查询出来,一般需要使用join语句,需要表进行关联,但是嵌套查询可以实现了按需查询,避免了n+1的问题,一般要先查单表的数据,这是一次查询,然后根据单表的id,跟多表的一方进行关联查询,需要n次关联的数据,就会有n次查询。如果需要全部展示关联表的数据,使用该方式就会造成n+1的问题,推荐使用嵌套结果的方式。

相关文章

  • (6)联合查询

    1.嵌套结果 这里先展示一对多的例子,一对一的例子暂时不展示了,区别一对多的关联查询使用collection进行映...

  • Laravel UNION联合查询并分页

    UNION联合查询并分页 联合查询用于将两个或更多查询的结果集组合为单个结果集,该结果集包含联合查询中所有查询的全...

  • MySQL实战6 分页查询和联合查询

    MySQL实战 目录 1.分页查询 案例:查询前5条员工数据 注意:如果从第一条开始,这个0可以省略:SELECT...

  • 联合查询

    一、定义 联合查询是将多次查询(多次select语句),在记录上进行拼接(字段不会增加) 1.1基本语法 多条se...

  • 联合查询

    一.外键(foreign key) 外键用于记录表之间的联系外面的键(键不在自己表中):如果有一张表中有一个字段(...

  • 联合查询

    将多条查询语句的结果合并成一个结果语法:查询语句1union查询语句2union... 引入案例:查询部门编号>9...

  • 联合查询

    一、含义 union:合并、联合,将多次查询结果合并成一个结果 二、语法 查询语句1union 【all】查询语句...

  • 联合查询

  • 实现无限级分类的数据库设计及sql查询

    创建表 查询数据 联合查询join

  • mysql联合查询

    进阶9:联合查询 /*union 联合 合并:将多条查询语句的结果合并成一个结果 语法:查询语句1union查询语...

网友评论

      本文标题:(6)联合查询

      本文链接:https://www.haomeiwen.com/subject/bhbmtqtx.html