扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
作者:Leonard Richardson 来源:www-128.ibm.com 2007年9月15日
关键字: 软件
如果更改 PhoneNumber
对象的一个成员,则该更改被自动镜像映射至数据库:
|
这只是一个警告:SQLObject 不允许更改对象的主键。通常最好是让 SQLObject 来管理表的 id
字段,即使是您不使用 SQLObject 时碰巧用另一个字段作为主键。
删除特定行对象的方法是将其 ID 传递到其类的 delete()
方法中:
|
到目前为止,一直用 14 字符美国格式传递电话号码。数据库模式被设计成接受这种格式的数字,这暗示着底层应用程序 —— 不管怎样 —— 都希望数字是这种格式。尽管如此,代码不能确保笨拙的用户或程序员漏洞不会导致未正确格式化的数据放入 number
字段中。
SQLObject 通过允许定义验证和转换入站数据的钩子方法来解决这个问题。可以为表中的每个字段定义一个方法。字段的钩子方法命名为 _set_[field name]()
,不管是作为 create
操作还是 update
操作的一部分,每当要为该字段设置一个值时,都会调用该方法。钩子方法应(可选)将入站值转换为可接受格式,然后设置该值。否则,它应抛出异常。要实际设置一个值,该方法需要调用 SQLObject 方法 _SO_set_(field name)
。
清单 4 展示了 PhoneNumber
的 _set_number()
方法。如果电话号码完全没有格式化,比如 4155551212,则该方法将该数字格式化为 (415) 555-1212。否则,如果数字格式不正确,该方法会抛出 ValueError
。正确格式化的电话号码 —— 或者是转换为正确格式的电话号码 —— 被正确传递给 SQLObject 的 _SO_set_number()
方法。
清单 13. PhoneNumber 的 _set_number () 方法
|
到目前为止,看到的所有操作都针对单个表:phone_number
。但真正的数据库应用程序通常具有多个相关表。SQLObject 允许将表之间的关系定义为外键。作为演示,我们将一个小的数据库规范化(normalization)应用于上一示例,将 PhoneNumber
的 owner
字段分割到单独的 person
表中。清单 14 所示的代码保存在名为 PhoneNumberII.py 的文件中。
|
该 PhoneNumber
类具有与旧类相同的成员,但它的 owner
成员是对 person
表的主键的引用,而不是对 phone_number
表中字符串列的引用。这使得表示具有两个电话号码的个人成为可能:
|
Person
的 numbers
成员,一个 SQLObject MultipleJoin
,使得基于 person
到 phone_number
的连接进行查询变得容易:
清单 16. 基于 person 到 phone_number 的连接的查询
|
同样,SQLObject 允许使用 MultipleJoin
类进行多对多连接的查询。
SQLObject 的一个常见用途是为另一个应用程序创建的数据库提供 Python 接口。SQLObject 有多个特性可用于实现这一点。
如果正在使用数据库中已经存在的表,则不需要在 Python 中定义列。SQLObject 可以通过数据库内省来提取它需要的信息。例如,清单 17 中的代码保存在 PhoneNumberIII.py 中。
|
该类将使用现有 phone_number
数据表的属性。您可以与它交互,就好像已经手动定义了该类及其所有列一样,如前面的示例所示。使用 SQLObject,只需要编写表定义一次 —— 用 SQL 还是用 Python 编写就取决于您了。
但是,该特性又带来了数据库的选择问题。例如,该特性完全不能用于 SQLite。它基本上能用于 MySQL,但不能提取外键关系。如果使用的是 MySQL,而且想要为表定义外键,则需要在从数据库中加载模式之后,编写代码定义这些字段。
上一部分中的代码假设现有表符合 SQLObject 的命名约定(例如,表的主键字段名为 id
,且列名中的词用下划线分隔)。表的命名约定在 Style
类中定义。
SQLObject 提供了一些与常见数据库命名约定对应的 Style
类。例如,如果列名类似 likeThis
而非 like_this
,则可以使用 MixedCaseStyle
:
|
如果没有预包装的 Style
类符合您的需要,那么您可以定义 Style
基类的子类,并定义自己的命名约定。在最坏的情况下,如果表的字段名分配得毫无道理,则可以逐个命名每个字段。
SQLObject 想让您用面向对象的方式而非关系方式进行思考。这有利于您的理解和您的编程生产率,但不利于性能。毕竟,数据库仍是关系型的。如何标记呼叫过的每个电话号码?使用 SQL,您将使用单个 UPDATE
命令。使用 SQLObject,您需要迭代通过整个结果集,并修改每个对象的 last_call
成员,这是非常低效的。
SQLObject 为开发人员时间牺牲了处理器时间。这通常是好的交易,但甚至在简单的应用程序中,您也可能需要下降一个级别到达 Python 数据库接口,为一些关键路径的操作编写原始 SQL。
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者