一、引言
在上一篇文章中 SQLAIchemy 异步DBManager封装-01入门理解 我们深入讨论了SQLAlchemy异步DBManager整体的封装结构与思路。详细地介绍了如何封装添加和批量添加的操作方法,并通过实际示例进行了演示。SQL 全称是结构化查询语言,无疑查询是最复杂的部分。因此,在这篇文章中,我将详细介绍如何封装通用的数据库查询方法,并通过具体的示例来讲解这一过程,使得这一复杂的任务变得更为简单。
二、通用查询封装
指定主键id查询
1 | python复制代码class DBManager(metaclass=SingletonMetaCls): |
这个封装很简单,直接看demo吧
1 | python复制代码class UserTable(BaseOrmTableWithTS): |
查询单条
1 | python复制代码@with_session |
查询无疑就只有两种结果单条、多条结果数据。这里统一封装一个 _query 通用查询方法,以供内部使用。
- 支持指定查询的列(cols)
- 条件查询(conds)
- 排序(orders)
- 分页(limit、offset)
主要封装就是利用 sqlaichemy 提供的 select 语法进行组织sql,通过 column 兼容列名字段字符串列表。query_one 方法,如果指定了 cols 返回字典格式,不指定则是库表映射类实例对象,一开始封装的时候我想统一出参都是返回 库表映射类实例对象 。
1 | python复制代码query_ret = cursor_result.mappings().one() or {} |
如果是 id as user_id 取别名查询会导致映射不上,但可以查询时不指定别名,orm_table_obj.to_dict(alias_dict={"id": "user_id"})
时进行别名转换,还有一些flat 扁平化、统计数量的时候都不能使用 orm_table(**query_ret)
故而不好统一,再实际web场景中,出参还是要转成dict、json格式化进行响应,故而进行保留。看看具体使用效果
1 | python复制代码from sqlalchemy import String, func, label |
查询结果
1 | python复制代码指定列名 ret {'username': 'hui', 'age': 18} |
查询多条
1 | python复制代码@with_session |
查询多条与query_one一致内部调用 _query() 获取查询结果集,最后通过 cursor_result.mappings().all()
、cursor_result.scalars().all()
获取列表数据,同样支持单字段扁平化处理,还支持分页处理。具体看如下例子
1 | python复制代码from sqlalchemy import String, func, label, or_ |
查询结果
1 | python复制代码查询全部 [1, 2, 3, 4, 5, 6] |
单字段扁平化处理,可以节省获取查询数据后再进行扁平化处理的一步操作。看看下面没有扁平化处理
1 | python复制代码user_infos = await UserManager().query_all(cols=[UserTable.id]) |
上面的获取某业务的所有id,计算总数等,直接获取扁平化的结果,有时还是比较实用。
分页查询
1 | python复制代码async def list_page( |
这里分页查询就用 query_one 查询总数,query_all 分页查询,curr_page 当前页与 page_size 每页大小计算数据偏移量 offset,然后通过 asyncio.gather 并发执行获取结果。
1 | python复制代码total_count, data_list = await UserManager().list_page( |
分页查询结果
1 | python复制代码分页查询 total_count 5 |
这里的分页查询没有使用 with_session 装饰器,由于 asyncio.gather 并发操作原因不能共享数据库会话 session,需要单独的 session,不然会报如下错误。
sqlalchemy.exc.InvalidRequestError:无法在上下文管理器内的已关闭事务上进行操作。 请先完成上下文管理器,然后再发出进一步的命令。
三、封装说明
SQL 的话还是查询用的多,查询也复杂,这里的话只封装了一些通用的查询操作,有一些分组查询、连表查询等我都没有封装,我认为这些操作还是写原生sql更直观一些,用ORM进行组装这些操作会感觉语法很别扭不简洁。如何执行原始sql,请看下一篇。SQLAIchemy 异步DBManager封装-03得心应手
四、Github源代码
源代码已上传到了Github,里面也有具体的使用Demo,欢迎大家一起体验、贡献。
HuiDBK/py-tools: 打造 Python 开发常用的工具,让Coding变得更简单 (github.com)
本文转载自: 掘金