1.1. 前言
在上一篇文章我们展示了使用装饰器来完成拆分后的编写SQL。好处是让代码变的更加的厉害,更容易的应变未来需求的变更了。但是,麻烦的是免不了需要添加新的装饰器。当然这对哪些较劲的来说肯定还说:之前的开发麻烦,代码有没减。这种效果当然也不是我想要的。
下面我们就来使用“动态装饰器”来实现,让我的代码更加的少。文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_5/
1.2. 回顾和找相同
回顾之前装饰器的3个方法(join_order、join_order_good、join_coupon),细心的会发现它们里面的代码几乎是相同的,除了需要关联的字段和调用获取数据方法如下表:文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_5/
装饰器方法 | 装饰器中需要调用的方法 | 拼凑时需要关联的字段 |
join_order | get_order_info | user_id |
join_order_good | get_order_good_info | order_id |
join_coupon | get_coupon_info | order_id |
通过比较代码和分析。我们想我们能不能将 装饰器中需要调用的方法 和 拼凑时需要关联的字段 通过变量的方式带入装饰器,这样我们就可以使用一个装饰器来满足所有装饰器的功能呢?答案是肯定的。文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_5/
1.3. 实现程序
我们通过实现一个动态装饰器方法(join_data)来完成我们的目标。这个装饰器有两个参数func_name、col_name:文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_5/
func_name:需要动态执行的方法名。文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_5/
col_name:两个结果集关联的字段。文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_5/
完整程序如下:文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_5/
#!/usr/bin/env python # -*- coding:utf-8 -*- import pandas as pd import mysql.connector import sys import sys reload(sys) sys.setdefaultencoding('utf-8') def get_user_info(user_ids, conn=None): ''' 通过user_id获得用户信息 ''' user_sql = ''' SELECT user_id, name FROM user WHERE user_id IN({user_ids}); '''.format(user_ids = ','.join(user_ids)) user_info = pd.read_sql(user_sql, conn) return user_info def get_order_info(user_ids, conn=None): ''' 通过 用户ID 获得订单信息 ''' order_sql = ''' SELECT user_id, order_id, num FROM orders WHERE user_id IN({user_ids}); '''.format(user_ids = ','.join(user_ids)) order_info = pd.read_sql(order_sql, conn) return order_info def get_order_good_info(order_ids, conn=None): ''' 通过上面获得的 订单ID 获得订单商品信息。 ''' order_good_sql = ''' SELECT order_id, good_name FROM order_good WHERE order_id IN ({ids}); '''.format(ids = ','.join(order_ids)) order_good_info = pd.read_sql(order_good_sql, conn) return order_good_info def get_coupon_info(order_ids, conn=None): ''' 通过 订单ID 获得券信息 ''' coupon_sql = ''' SELECT order_id, name FROM coupon WHERE order_id IN({ids}); '''.format(ids = ','.join(order_ids)) coupon_info = pd.read_sql(coupon_sql, conn) return coupon_info def join_data(func_name, col_name): ''' 添加能通过订单ID查找出来的信息 ''' def _join_data(func): def __join_data(*args, **kargs): func_info = func(*args, **kargs) ids = func_info[col_name].astype(str) info = eval(func_name)(ids, **kargs) new_order = func_info.merge(info, left_on=col_name, right_on=col_name, how='left') return new_order return __join_data return _join_data @join_data('get_coupon_info', 'order_id') @join_data('get_order_good_info', 'order_id') @join_data('get_order_info', 'user_id') def get_order_detail(user_id, conn=None): ''' 拼凑获得订单信息 ''' user_ids = [str(user_id)] return get_user_info(user_ids, conn=conn) if __name__ == '__main__': conf = { 'host' : '127.0.0.1', 'port' : '3306', 'database' : 'test', 'user' : 'root', 'password' : 'root' } conn = mysql.connector.connect(**conf) print get_order_detail(10, conn=conn) conn.close()
最后结果:文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_5/
user_id name_x order_id num good_name name_y 0 10 HH 1 11111 order_good_1 coupon_1 1 10 HH 1 11111 order_good_2 coupon_1 2 10 HH 2 22222 order_good_3 NaN 3 10 HH 2 22222 order_good_4 NaN 4 10 HH 3 33333 order_good_5 coupon_3 5 10 HH 3 33333 order_good_6 coupon_3 6 10 HH 4 44444 order_good_7 NaN 7 10 HH 4 44444 order_good_8 NaN 8 10 HH 5 55555 order_good_9 coupon_5 9 10 HH 5 55555 order_good_10 coupon_5
源代码:use_dynamic_decorator文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_5/
现在来看一下我们的业务代码。代码量上少了吧。现在的代码量将会比你的jion还少了吧一个业务只需要在方法上面不端的添加注解(annotation)就好了。文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_5/
我们来看一下他的应变需求变化的能力。现在业务部需要展现券的信息了,这时我们只需要将如下代码删除了:文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_5/
@join_data('get_coupon_info', 'order_id')
现在有一个需求,订单需要展示门店的信息(订单和门店是以store_id关联)。这时我们只需要查看是否有人实现过相关的方法比如get_store_info,之后只需要在业务方法get_order_detail的头上加上注解@join_data('get_store_info', 'store_id')。然后就能满足业务的需求了。文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_5/
而反过来看,如果使用join的方法写的代码。你是不是需要先看懂之前的join是怎么写的,还要考虑我的代码应该要怎么添加。而且join的代码的扩展性无疑是很差的,并且对数据库的查询的并发也会大打折扣。文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_5/
如果到了现在你们还说使用join能提高开发效率。会增加代码量的。我只能说:对不起,我错了,原谅我的无知吧。文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_5/
文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_5/
昵称:HH
QQ:275258836
ttlsa群交流沟通(QQ群②:6690706 QQ群③:168085569 QQ群④:415230207(新) 微信公众号:ttlsacom)文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_5/
感觉本文内容不错,读后有收获?文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_5/
逛逛衣服店,鼓励作者写出更好文章。文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_5/ 文章源自运维生存时间-https://www.ttlsa.com/mysql/using_join_no_programing_5/

1F
:evil: :!: :!: aaa顶顶顶顶