zoukankan      html  css  js  c++  java
  • Yii2 ActiveRecord查询初探

    梳理一下Yii2中ActiveRecord一次查询的大致流程,理解如下几个问题:

    (1)ActiveRecord与ActiveQuery何时产生联系;

    (2)ActiveQuery怎样与数据库连接Connection产生关系;

    (3)ActiveRecord查询为何能返回ActiveRecord对象;

    (4)join(),joinWith()与with()有什么关系与区别;

    (5)ActiveRecord关联查询怎样做到面向对象访问关联属性,它与普通的Query查询有何区别。

    1.相关类结构

    (1)ActiveRecord相关类:

    yiidbActiveRecord extends yiidbBaseActiveRecord extends yiiaseModel

    (2)ActiveQuery相关类:

    yiidbActiveQuery extends yiidbQuery

    另有一些Trait提供关联查询功能,这里暂不详细列出,当作query类方法来描述。

    (3)yiidbCommand  yiidbConnection 与yiidbQueryBuilder联合起来,基于Pdo实现基本的数据库连接与查询。

    2.ActiveRecord::find()->one();执行流程:

    (1)ActiveRecord::find()实例化一个ActiveQuery对象并返回;

    (2)ActiveQuery::one()会调用Query::one()获取查询结果,并对结果进行populate(),以便把数据库查询的数组结构的结果集渲染为具体的ActiveRecord对象结果集;

    (3)Query::one()执行流程:

        1)通过QueryBuilder::build()构造查询所需的sql语句与关联参数;

        2)调用Connection::createCommand()实例化一个Command对象;

        3)通过Command::queryOne()获取查询结果集。

    (4)Command::queryOne()实际会调用Command::queryInternal():

        1)首先判断是否开启了数据缓存,若开启则先在缓存中查找结果集,没有则继续执行以下步骤,这里对Yii的数据缓存不展开讨论;

        2)执行Command::prepare()经由Connection获得当前数据库连接的Pdo对象,通过Pdo对象的prepare()方法获得一个PdoStatement对象;

        3)通过上一步获得的PdoStatement对象获取并返回查询结果集。

    (5)ActiveRecord的populate过程:

        1)根据数据库查询结果集的数据构造对应的主ActiveRecord对象;

        2)通过findWith()处理eagerLoading类型的关联属性,也是ActiveRecord查询结果可以以面向对象的方式访问关联查询结果的关键所在,这一问题并未在上图中展开,下面是具体分析。

    3.join(), joinWith()与with()

    通过阅读源码大概掌握了这三个方法干了些什么:

    (1)join()是yiidbQuery提供的方法,所以并未与ActiveRecord产生关联,只是用于构造Query对象的$join属性,以便构造sql语句使用;

    (2)joinWith()是yiidbActiveQuery的方法,抛开它支持的多种关联定义方式,仅仅是将关联信息放入ActiveQuery的$joinWith属性中;

    (3)with()是yiidbActiveQueryTrait提供的方法,ActiveQuery使用了这个Trait。同样抛开它多样化的参数,它仅仅是将关联属性信息存入ActiveQuery的$with属性中。

    到这里没有什么进展,还要继续看查询过程中哪里用到了$join,$joinWith与$with这三个属性:

    (1)在ActiveQuery::prepare()方法中调用了buildJoinWith()方法,这里处理$joinWith属性内容,将其全部加到$join属性中,并将eagerLoading为true的内容同时加入到$with属性中,至此,$joinWith属性的任务结束;

    (2)在ActiveRecord::populate()方法中调用了findWith()方法,这里处理$with属性的内容,对每条查询结果逐个查询$with中定义的关联属性结果集并实例化为对应的关联ActiveRecord对象,通过主ActiveRecord对象的populateRelation()方法实现属性关联。至此,ActiveRecord的查询结果已经可以像访问属性一样访问关联查询结果了。

    4.Query与ActiveQuery在联表查询上的区别

    (1)Query处理联表查询是中规中矩的sql查询方式,所有关联结果与主表结果在一次查询中获得并在同一结果集中返回;

    (2)ActiveQuery的联表查询比较特殊,它为了实现面向对象的关联属性访问方式,需要经过多次查询来构造关联ActiveRecord对象:

        1)join()与joinWith()方法均是$join属性的定义入口,在ActiveQuery中虽然最终构造出的sql语句包含$join属性定义的所有关联,但除非在select()方法中包含关联属性,否则默认生成的sql只查询主表的字段,查询结果中将不包含任何关联表数据,而且在populateRecord过程中也只能处理主表字段;

        2)关联属性如果来自with()或指定eagerLoading为true的joinWith()方法,即被包含在$with属性中,则在渲染完主表的查询结果后,会逐个查询关联结果并渲染关联属性;

        3)若通过joinWith()定义关联并指定eagerLoading为false,则直到显示读取该关联属性时才会执行关联结果查询与渲染,这就是LazyLoading。

  • 相关阅读:
    Spring在代码中获取bean的几种方式
    SpringBoot学习:获取yml和properties配置文件的内容(转)
    SpringBoot 使用 @Value 从 YAML文件读取属性(转)
    SpringBoot yml 配置
    Springboot+shiro配置笔记+错误小结
    shiro退出登陆清空缓存实现
    springboot(十四):springboot整合shiro-登录认证和权限管理(转)
    Apache Shiro 简单概念
    漫步Facebook开源C++库Folly之string类设计(散列、字符串、向量、内存分配、位处理等,小部分是对现有标准库和Boost库功能上的补充,大部分都是基于性能的需求而“重新制造轮子”)
    Windows Vista 的历史地位
  • 原文地址:https://www.cnblogs.com/ling-diary/p/9193253.html
Copyright © 2011-2022 走看看