导读:
Pink是仓库人员作业流程操作使用的系统,包含App、后台服务、供应链后台等。即登记商品入库检查到出库的一系列动作的app,也可以指实现商品入库检查到出库的系统统称,常用功能:扫码入货,分拣,质检,鉴别,拍照留档,防伪,复检,出库,退货等功能。
以下为正文。
对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系型数据库(如MySQL)存在的互不匹配的现象的技术。简单来说,ORM是通过使用描述对象和数据库之间映射的元数据,在业务逻辑层和数据库层之间充当了桥梁的作用,将程序中的对象自动持久化到关系数据库中。
目前供应链Pink自动化项目使用的框架是Django,它有自带的ORM框架,在模型层将数据库操作映射为对类或者对象的操作,通常把一个类和一个表,类的每个实例和表中的每条记录,类的每个属性和表中的每个字段一一对应。不需要编写sql,就能够像操作对象一样从数据库获取数据。
Django框架中ORM示意图如下:
我们在使用Django框架开发应用的过程中,不可避免地会涉及到数据的DML操作(增、删、改、查),那么我们需要在应用程序中编写原生SQL语句,然后使用pymysql模块远程操作MySQL数据库针对应用程序的数据操作,直接编写原生SQL语句会存在几方面的问题,影响开发效率:
1. SQL语句的编写效率问题:需要耗费一大部分精力去优化SQL语句;
2. 数据库兼容问题:针对MySQL开发的sql语句无法直接应用到oracle数据库上;
3.获取、关闭连接的方式麻烦、操作对象的方式繁琐、影响开发速度。
为了解决上述问题,django引入了ORM的概念在pymysq之上又进行了一层封装,对于数据的操作,我们无需再去编写原生SQL,取而代之的是基于面向对象的思想去编写类、对象、调用相应的方法等,ORM会将其转换/映射成原生SQL然后交给pymysql执行,如下图所示:
最开始我们使用的是原生PyMySQL模块,但是在使用过程中发现需要在业务逻辑代码中编写SQL语句来操作数据的DML,后续还需要对获取的查询数据处理。这些代码通常都是重复的,使用起来非常不方便。就像是这样:
相对来说,ORM就显得简单易用很多,它自带丰富的API,可以直接使用对应方法来进行数据库的DML,并且不再需要对返回数据进行转换,可供直接调用。虽然ORM会在一定程度上牺牲程序的执行效率,但是可以让我们更专注于业务逻辑的处理,提升了开发效率,不再需要在业务代码中编写一堆SQL语句,增加了代码的简洁性、可读性以及易于维护性。隐藏了数据访问细节,更好地做到数据隔离。可以对比看看下图:
Python中常用的ORM主要有:SQLObject、Storm、Django’s ORM、Peewee、SQLAlchemy,我们主要调研了这几种ORM的特性以及对使用的优缺点做分析:
ORM | 优点 | 缺点 |
SQLObject | 采用了ActiveRecord 模式 ,易懂 代码库相对较小 | 命名遵循了Java 的小驼峰风格 不支持数据库session隔离工作单元 |
Storm | 清爽轻量的API,短学习曲线、长期可维护性 不需要特殊的类构造函数,也没有必要的基类 | 需手工写表格创建的DDL语句, 贡献者必须把版权给Canonical公司 |
Django’s ORM | 学习曲线短 、易用 和Django紧密集合,使用约定俗成的方法去操作数据库 | 不好处理复杂的查询,强制开发者回到原生SQL 紧密和Django集成,使得在Django环境外很难使用 |
Peewee | Django式的轻量API,易懂、易用 容易和任意web框架集成 | 不支持自动化 schema 迁移 多对多查询写起来不直观 |
SQLAlchemy | 企业级 API,使得代码有健壮性和适应性 能轻松写复杂查询 | 工作单元概念不常见 重量级API,导致学习曲线长 |
最终我们决定使用Peewee,主要具有以下优势:
1. 使用SQLAIchemy内核,但是比SQLAIchemy更轻量;
2. 可使用命令创建Model,也可以处理复杂的查询,不需要系统学习就可操作使用;
3. 用纯Ptyhon编写,提供了多种数据库的访问,支持Sqlite、Mysql、Postgresql和Cockroachdb等;
4. 使用Django式的API,使用直观且能与任意web框架集成。
Peewee是一种简单而小的ORM。它有很少的(但富有表现力)的概念,使它易于学习和直观的使用。
在Python中成功创建一个Model,需要有相应的数据库信息,命令如下:
python -m pwiz -e mysql -u user -H host --password -t table schema > XXModel.py
创建成功后自动生成一个.py文件,如下图:
新增数据有很多种方式,主要是使用create()、save()、insert()、insert_many()。这里没有指定主键,peewee 会自动增加一个名为 id 的自增列作为主键。
1. save() :当一个Model实例没有主键时,此时使用save()就是新增数据 。
2. create() :Model.create()向数据库中插入一条记录,并返回一个新的实例。
3. insert() :只插入数据而不创建模型实例,返回新行的主键。
4. insert_many()
语法:insert_many(rows, fields=None)
说明:当rows是字典列表时,fields不需要传;当rows是元组列表时,必须指定fields。
具体使用请见下图:
1. save()+主键 :save()方法可以插入一条记录,一旦模型实例具有主键,任何后续调用save()都将导致 update而不是另一个insert。模型的主键不会改变。
2. update() :也可以使用update()来更新数据,一般都会搭配where()使用。
2. delete_instance() :删除给定的实例。delete_instance()直接执行删除了,不用调用execute()方法。
下面主要介绍比较常用的一些查询方法。
1. get() :可以直接使用get()获取单条数据,在参数中传递查询条件。
2. select():使用select()查询多条数据,一般结合where()使用,不添加where()是查询整个表的内容。
3. 组合查询 :table.select(...).where(...).order_by(...).limit(...)...
4. 联表组合查询:下面的例子主要使用联表查询+子查询来展示一些比较复杂的用法。
# 根据运单号联表+子查询开到时间,并修改为24小时前
update tebleC
set not_found_time = DATE_SUB(not_found_time,interval 1 day)
where item_id =(select poi.id
from tebleA poi
left join tebleB pid
on pid.id = poi.in_id
where pid.e_code = 'SFXXXXXXXXX');
5. 查询条件 :当查询条件不止一个,需要使用逻辑运算符,但是Peewee中不支持and、or、not等,可以使用Peewee封装好的运算符,如下:
注意:有多个条件时,每个条件必须用 () 括起来。
逻辑符 | 含义 | 举例 |
& | and | tableA.select().where((tableA.storage_code == 'TEST009') & (tableA.repository_code == '123')) |
| | or | query = tableA.select().where((tableA.storage_code == 'TEST009') | (tableA.repository_code == '123')) |
~ | not | tableA.select().where(~tableA.storage_code == '123') |
6. 比较符 :在查询、更新、删除数据的时候,经常会带有Where()条件语句。Peewee支持以下类型比较符:
运算符 | 含义 |
== | 等于 |
< | 小于 |
<= | 小于等于 |
> | 大于 |
>= | 大于等于 |
!= | 不等于 |
<< | x in y,其中 y 是列表或查询 |
>> | x is y, 其中 y 可以是 None |
% | x like y ,区分大小写 |
** | x like y ,不区分大小写 |
Pink自动化实现面向对象编程后,ORM框架的使用是里程碑式的一步了。除了ORM,还可以引用很多优秀的设计思想和框架来建设自动化,比如:接口使用对象传参,引入**kwargs拓展参数,使用策略模式等,接口API使用更灵活、易于维护,避免大量代码重复调用。
自动化测试带来的收益很明显,具体体现在效率上的提升,如:从前手工造数据(某些复杂的单据)会占用很大的的工作量,往往受各种约束条件可能需要好几个小时才能实现,现在通过Mock订单2s的时间便可完成,同时也为开发人员自测联调节省了很多的时间。总体测试流程上,时间缩短了百分之50%以上,能够更加快速且精准地定位并发现问题,节省了测试时间。
使用面向对象对面编程,中间经历了很多试探与磨合,目前也已开始接入造数工厂使用,相信可以为更多的小伙伴提升工作效率,最后感谢团队的各位小伙伴以及正在看这篇文章的小伙伴,有问题可以在评论区讨论。
*文/三岁