从实践当中总结的数据库访问接口 -- PHP

宏哥 发布于 2012/10/18 14:48
阅读 867
收藏 2

通过实践的反馈, 不断优化逼近, 最终统一了以下数据库访问接口:



   /** 
    * @param   integer  type: self::SELECT, self::UPDATE, etc
     * @param   string   SQL statement
     * @param   Boolean $as_object Return Result set as Object if true, default FALSE
     * @param   Array $params  Query parameters of SQL, default array()
     * @param   String $stmt_name The query is Prepared Statement if TRUE,
     *          Execute Prepared Statement when $param is Not NULL
     *          Prepare Statement when $param is NULL
     *
     * Return Database_Query
     */
    public static function 
    query($type, $sql = NULL ,$as_object = false,$params = array(),$stmt_name = NULL)


第一个参数, 是由于数据库执行不同语句, 对结果集的处理策略需要不同

第二个参数,  Raw Sql, 要保证是escape 的SQL, 或者 带参数传入的SQL

第三个参数, 由于PHP提供了数组和对象两种获取结果集的方法, 通过这个参数控制策略

第四个参数,  当执行带参数SQL,或者执行prepared statement, 可以通过这个参数传入 SQL/Statment的参数

第五个参数, prepared statement 的名字.   当sql 不为NULL, 则params必须为NULL, 函数行为为编译prepared statement, 当SQL为NULL, params 必须不为NULL, 这是执行预编译存储过程

此函数, 基本上覆盖了RDBMS能够执行的所有操作. 提供所有数据库操作的唯一入口. 其他的如通过 key->value对来 insert/update数据库的函数,都为对此函数的调用.

加载中
0
JFinal
JFinal

@JFinal 的 ActiveRecord 与此设计基本一致,主要就两个地方不同:

1:无 type 这个参数,而是使用方法名来区分,如:find(...)与query(...) 对应selet语句,而update(...)对应update语句。

2:无as_object参数,也是使用方法名区分,如 find(...)系列的方法相当于 as_object = true,而 query(...)系列的方法相当于 as_object = false。

0
galaxy58
galaxy58
难道优秀的设计最终都走向一致、相似?
0
JFinal
JFinal

引用来自“galaxy58”的答案

难道优秀的设计最终都走向一致、相似?
有这个可能,例如自打 ruby on rails  出现以后,现在越来越多的 web framework 与其相似了 :)
0
宏哥
宏哥

引用来自“JFinal”的答案

引用来自“galaxy58”的答案

难道优秀的设计最终都走向一致、相似?
有这个可能,例如自打 ruby on rails  出现以后,现在越来越多的 web framework 与其相似了 :)

倒不是因为 R&R的原因, 其实很早在C++就有类似的东西, 有个项目叫做ocicpplib. 至少10多年以前.

其实帖子这个接口设计, 是针对 Postgresql的, 如果Oracle, 它有能力进行Bind, 使得传入参数, 也可以同时是输出, 这点在存储过程体现特别明显, 类似引用传入. 

那么, 这个接口就无法提供这个功能了. PG没有这个功能. 通常来说,如果需要多个返回, 可以用返回结果集代替.

实际上, 数据库之间, 本质不兼容. 

JFinal
JFinal
好的设计经得住时间的考验。数据库之间本质上不兼容的,非要去兼容会增大复杂度,结果可能就是得不偿失
0
宏哥
宏哥

@jFinal , 还有一个区别.

实际上数据库可以执行这种逻辑

DB::query(DB::SELECT,'insert into t(...) values(.....) returnning id,col1....coln')

以SELECT逻辑, 执行插入语句, 返回 ID或者多个字段值

0
JFinal
JFinal

引用来自“宏哥”的答案

@jFinal , 还有一个区别.

实际上数据库可以执行这种逻辑

DB::query(DB::SELECT,'insert into t(...) values(.....) returnning id,col1....coln')

以SELECT逻辑, 执行插入语句, 返回 ID或者多个字段值

这种用法没用过,感觉很酷      哪天会用后,看能不能给 @JFinal 添加这个特性
0
宏哥
宏哥

引用来自“JFinal”的答案

引用来自“宏哥”的答案

@jFinal , 还有一个区别.

实际上数据库可以执行这种逻辑

DB::query(DB::SELECT,'insert into t(...) values(.....) returnning id,col1....coln')

以SELECT逻辑, 执行插入语句, 返回 ID或者多个字段值

这种用法没用过,感觉很酷      哪天会用后,看能不能给 @JFinal 添加这个特性

这个是"真正"的数据库都支持的操作, 特别对应 自增ID, 多个默认值字段时候,或者触发器有权修改插入数据的情况, 一次原子操作, 返回所有实际的数据库当中数据,严格的一致性.

如果要兼容mysql, 就不能有这种写法.

Convention over configuration, Decision Over Convention.

0
JFinal
JFinal

引用来自“宏哥”的答案

引用来自“JFinal”的答案

引用来自“宏哥”的答案

@jFinal , 还有一个区别.

实际上数据库可以执行这种逻辑

DB::query(DB::SELECT,'insert into t(...) values(.....) returnning id,col1....coln')

以SELECT逻辑, 执行插入语句, 返回 ID或者多个字段值

这种用法没用过,感觉很酷      哪天会用后,看能不能给 @JFinal 添加这个特性

这个是"真正"的数据库都支持的操作, 特别对应 自增ID, 多个默认值字段时候,或者触发器有权修改插入数据的情况, 一次原子操作, 返回所有实际的数据库当中数据,严格的一致性.

如果要兼容mysql, 就不能有这种写法.

Convention over configuration, Decision Over Convention.

学习了,一直都用的 mysql,有时间的时候研究一下 PG 
0
宏哥
宏哥

引用来自“JFinal”的答案

引用来自“宏哥”的答案

引用来自“JFinal”的答案

引用来自“宏哥”的答案

@jFinal , 还有一个区别.

实际上数据库可以执行这种逻辑

DB::query(DB::SELECT,'insert into t(...) values(.....) returnning id,col1....coln')

以SELECT逻辑, 执行插入语句, 返回 ID或者多个字段值

这种用法没用过,感觉很酷      哪天会用后,看能不能给 @JFinal 添加这个特性


这个是"真正"的数据库都支持的操作, 特别对应 自增ID, 多个默认值字段时候,或者触发器有权修改插入数据的情况, 一次原子操作, 返回所有实际的数据库当中数据,严格的一致性.

如果要兼容mysql, 就不能有这种写法.

Convention over configuration, Decision Over Convention.


学习了,一直都用的 mysql,有时间的时候研究一下 PG 

你的 @jFinal 要进入主流的话, 就不能仅仅 "围绕" mysql来做设计.

数据库执行策略, 有很多不同. 有一点是普遍的, 任何SQL,你都不能假定它是"查询"或者"写入". 

对于数据库, 它只返回结果集, 对任何SQL执行,都是这个策略. 区别在于, SELECT关心的是结果集的数据, DELETE/UPDATE关心受影响数据, 而INSERT, 可以不关心,也可以关心实际插入数据的内容.

但是, mysql 不是这个策略. 

所以,如果你以mysql作为策略标准, 接口设计会有很多概念性错误.

所谓数据库"查询"其实是一次呼叫服务, 并不是SELECT, 任何呼叫都可以有结果集. 也可以同时有受影响数据.

JFinal
JFinal
的确是不能仅仅“围绕“mysql来做设计, @JFinal 刚开源那段时间,对 Oracle 支持的呼声是最高的,所以很快在下一版加入了 Oracle 支持。 JFinal 对Oralce 的支持一直在逐步完善,例如 JFinal 下一版 1.1.4 将对 Oracle 结果集的字段名大小写问题进行改进
0
放倒
放倒
谢谢。
返回顶部
顶部