写一个“特殊”的查询构造器 - (前言)

文章目录

写一个“特殊”的查询构造器 - (前言)

写一个“特殊”的查询构造器 - (一、程序结构,基础封装)

写一个“特殊”的查询构造器 - (二、第一条语句)

写一个“特殊”的查询构造器 - (三、条件查询)

写一个“特殊”的查询构造器 - (四、条件查询:复杂条件)

写一个“特殊”的查询构造器 - (五、聚合函数、分组、排序、分页)

写一个“特殊”的查询构造器 - (六、关联)

写一个“特殊”的查询构造器 - (七、DML 语句、事务)

写一个“特殊”的查询构造器 - (八、单元测试、收尾工作)

更新

此项目已经从 WorkerA 中拆分为独立项目,完整代码请到 wazsmwazsm/DB 中查看。

前言

对于后端程序员来说,数据库操作是必备知识,对数据的增删查改也是业务中最普遍、频繁的操作。

对于关系型数据库,如 Mysql、Postgresql 等,我们可以使用 SQL (Structured Query Language) 来操作我们的数据,如 “SELECT * FROM test;” 这类的 SQL 语句,大部分的编程语言如 PHP、Python、go 等都提供了相应的数据库扩展,可以方便的进行数据库连接、执行 SQL 获取结果。

但是,直接使用基础的扩展效率并不高,每次都要创建连接、手动写 SQL、对执行结果进行判断、将查询得到的数据进行处理等,代码的重用性和维护性并不是很好,在多人开发的时候更是不能保证代码质量。而在项目开发中,我们想要的是一个更好用的可维护的工具,此时,对代码的封装、模块化就显得尤为重要,于是出现了两种方案:查询构造器对象关系映射

  • 查询构造器 (query builder),顾名思义,它的目的就是以简便的形式构造、执行 SQL,为查询数据库的业务提供了方便好用的接口,一些知名的 web 框架如 PHP 的 Laravel、CodeIgniter、ThinkPHP 等都提供了好用的查询构造器。

  • 对象关系映射 (ORM) 是一种更面向对象的数据模型化操作,将数据库的数据映射成对象模型,数据库的直接操作对开发者透明,开发者只需关注对象模型即可,更符合面向对象程序思维。同样,很多框架也提供了 ORM 的方式去操作数据。

为什么要写查询构造器,我的需求是什么

写这个查询构造器的起因是 workerman,一个由 PHP 编写的、可以常驻内存的 Socket 框架。

当时选用 workerman 去做一个 webAPI 的项目,针对 workerman 的环境编写了一个简单的 http 框架 WorkerA,一是没有找到合适的 (在一个非典型 web 环境中,想要一个类似 laravel 那样方便的查询构造器),二是想要锻炼自己,于是选择了自己去写这个查询构造器。

如今该查询构造器已经完工,完整代码在我的框架核心代码中: 查看

Q&A

Q:为什么选择查询构造器而不是 ORM

A:对于我自己的需求,我需要一个简单好用又快速的工具,ORM 的性能和复杂性显然不合适。


Q:该查询构造器“特殊”在何处

A:区别于典型 web 的一次 HTTP 请求的代码运行周期,这个查询构造器除了可以使用在普通的 web 环境中,还支持常驻内存的环境,支持断线重连 (这个很重要)


Q:为什么选 PHP

A:因为我自己用 PHP 开发最多,重要的是 workerman 是 PHP 编写的。


Q:支持哪些数据库

A:目前支持了 Mysql、Postgresql、Sqlite 这三个数据库,而且全部通过了单元测试


Q:好的使用实践?

A:我在 workerman 的环境中使用的是单例模式,每个进程一个数据库连接单例模型。典型 web 环境下按照一般的查询构造器处理就行。同样常驻内存的情景可以自己写链接池之类的功能,当然这和查询构造器本身没有关系,一切由你的需求来决定。

需求和技术的选择 (想想自己想要什么)

底层驱动的选择:

  • php 提供了 mysql 和 pgsql 这些常用数据库的扩展,但是每个扩展暴露出的接口都不大一样,封装不便,pass

  • php 的 PDO 提供了多种数据库的底层驱动,统一了访问接口,prepare 方法可以有效的防止 SQL 注入,就选它

错误异常处理:

  • 使用 PHP 的 try catch 机制,使用内置的异常和 PDO 的异常进行异常抛出

代码结构的设计:

  • 查询构造器要支持多个数据库,我们要把相同的部分 (查询等) 封装起来,将不同的部分 (不同数据库的连接和设置) 独立开来,那么只需创建一个基类 (封装 PDO 的操作),每个数据库单独建立一个类继承基类,将各自差异的部分重写即可。

SQL 的构建:

  • sql 的构建属于字符串的操作,构建 sql 即是构造字符串,PHP 有丰富的字符串处理函数

好用和性能的均衡考虑:

  • 有些工具好用但是性能不一定好 (比如正则表达式),当然并不是说为了语言层面的极致性能而放弃一些便易性,查询构造器的瓶颈一般在于连接数据库的网络消耗和数据库对 SQL 的执行上。那么我们就以此作为平衡点,只要不比平衡点慢,我们可以选择更方便开发的方式写代码。

测试:

  • 选择 phpunit 作为单元测试工具,以可测试为前提拆分代码为最小单元,提升代码的可维护性

总体思路

进行相关的需求分析和技术选择后,我们得出了构建查询构造器的大概的思路:

  • 基于 PDO
  • 通过字符串操作构建 SQL
  • 将构造好的字符串交给 PDO 执行,获取结果
  • 以继承、重写的模式搭建代码的架子
  • 错误异常处理
  • 编写单元测试

理清思路,开始干活。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容