热搜: 分页类  验证码  PHP  Laravel  Jpgraph  windows7  Windows补丁  Swift  替换  收机 
  • 首 页
  • yii2的数据库层设计

       日期:2017-02-05     浏览:449    评论:0    
    核心提示:Yii2在M层的抽象做的很经典,值得分析理解。QueryBuilder不同的数据库引擎(mysql,oracle…)执行相同的SQL,可能语法有一些细微的差异,但是SQL整体语法差别不大,所以会定义一个QueryBuilder基类,它提供一般通用的SQL生成方法,具体每个数据库引擎继承Quer

    Yii2在M层的抽象做的很经典,值得分析理解。

    QueryBuilder

    不同的数据库引擎(mysql,oracle…)执行相同的SQL,可能语法有一些细微的差异,但是SQL整体语法差别不大,所以会定义一个QueryBuilder基类,它提供一般通用的SQL生成方法,具体每个数据库引擎继承QueryBuilder,如果存在细微差异只需覆盖特定的方法既可。

    简单说,QueryBuilder用来构造SQL语句(读SQL和写SQL都可以),但是并不执行它,通过调用它的where,groupBy,orderBy,select,insert等方法传入结构化的语句组成部分,最终由QueryBuilder返回一个字符串的SQL语句。

    Query

    仅提供查询能力,不支持修改,它也提供where,groupBy,select等方法(注意不支持insert,update这种修改操作),但是它本身没有生成SQL的能力,仅仅是在QueryBulder之上提供一个通用层,最终在调用它的one或者all方法时会将SQL的各个组成部分一次性交给QueryBuilder构造出SQL语句,那么Query对象怎么知道用哪个QueryBuilder呢?

    Query对象会通过application->get(“db”)拿到配置的数据库连接connection对象,这个connection对象自然是知道自己连接的是哪种数据库引擎,因此可以通过它拿到对应的queryBuilder对象。具体来说,connection对象创建时会从配置中取到这样的配置:

    return [
        'components' => [
            'db' => [
                'class' => 'yii\db\Connection',
                'dsn' => 'mysql:host=localhost;dbname=yii2advanced',
                'username' => 'root',
                'password' => '',
                'charset' => 'utf8',
            ],
    

    Connection对象根据dsn知道对应的数据库引擎,从而创建对应的schema对象:

    public $schemaMap = [
        'pgsql' => 'yii\db\pgsql\Schema', // PostgreSQL
        'mysqli' => 'yii\db\mysql\Schema', // MySQL
        'mysql' => 'yii\db\mysql\Schema', // MySQL
        'sqlite' => 'yii\db\sqlite\Schema', // sqlite 3
        'sqlite2' => 'yii\db\sqlite\Schema', // sqlite 2
        'sqlsrv' => 'yii\db\mssql\Schema', // newer MSSQL driver on MS Windows hosts
        'oci' => 'yii\db\oci\Schema', // Oracle driver
        'mssql' => 'yii\db\mssql\Schema', // older MSSQL driver on MS Windows hosts
        'dblib' => 'yii\db\mssql\Schema', // dblib drivers on GNU/Linux (and maybe other OSes) hosts
        'cubrid' => 'yii\db\cubrid\Schema', // CUBRID
    ];
    

    而这个Schema对象是每个数据库引擎各自实现的,它们有一个方法可以返回对应的QueryBuilder对象:

    /**
    * @return QueryBuilder the query builder for this connection.
    */
    public function getQueryBuilder()
    {
        if ($this->_builder === null) {
            $this->_builder = $this->createQueryBuilder();
        }
     
        return $this->_builder;
    }
    

    但是需要注意,虽然经过QueryBuilder生成了SQL,但是Query并不是自己直接执行这个SQL,而是将这个任务交给了下面这个类。

    Command

    这个类需要由connection对象创建的,内部保存了从connection对象取来的pdo数据库连接。command类的定位是直接执行SQL,也提供bind参数的能力,它不再限制SQL是读还是写,这也是为什么Query类不直接使用connection的pdo连接执行读SQL而是把构造来的SQL交给command,因为command类才是负责执行所有SQL的合适角色,职责集中在Command对象是一个合理的设计。

    根据这个认识,我们知道Command类可以直接执行裸SQL,读和写都是可以的。

    ActiveQuery

    之前的Query算一个调度者,它从用户收集查询的组成要素,交给QueryBuilder生成SQL,最后交给Command完成SQL的执行,拿回来的结果都是数组形式的一行一行的数据。

    ActiveQuery则是在Query基础上(继承自Query),额外提供了ORM能力,主要包含2点:数据库行映射为对象(就是指ActiveRecord,也是一个model),以及表的关联关系。

    我们知道Query的one和all都是返回关联数组形式的结果集,而ActiveRecord则覆盖了这两个方法,为每一行数据生成对应的activeRecord对象并把列值填充到对象里,这样就实现了数据库行和程序对象的自动映射,大概就是这种关系了。

     
    标签: SQL Yii
     
    更多>同类编程语言
    0相关评论

    推荐图文
    推荐编程语言
    点击排行
    网站首页  |  关于我们  |  联系方式  |  使用协议  |  版权隐私  |  网站地图  |  广告服务  |  网站留言  |  违规举报