ORM反射数据表到实体类--好用到哭泣

前言

为了避免sql注入或白盒漏洞问题,同时也是为了方便数据底层操作,工作中会尽量避免使用原生sql,而选择ORM。python中常用的有sqlalchemy库。该库的使用可以学习参考https://www.cnblogs.com/liu-yao/p/5342656.html
在使用过程中会发现需要自行创建一个class去映射数据表结构,然后通过操作class进行数据的增删改查等一系列操作。这个其实已经能满足日常的使用,但是在工作中我们常会选择数据分离,分工明确, 比如我就遇到需要设计底层DAL,提供统一的数据接口给所有业务,我们可以选择让业务线把设计好的表结构或者创建语句统一给我们,然后保存一个py文件去维护这些表信息,将表结构映射成model。
这种做法有以下几个问题:

  1. 修改表结构信息,需要动态修改py文件
  2. 业务线修改表结构可能不能完全同步到DAL层,导致业务逻辑出现瘫痪
  3. 对于线上环境,每次修改都需要重新部署上线,这是一个浪费人力和时间的事情,而且不能保证完全不出错。

基于以上考虑,我们会考虑,如何动态获取数据库中表结构的变化,这就是所谓的数据表反射成实体类(起初不知道这个概念,只能查询资料:如何动态生成数据表的model类)。

数据表反射成实体类

方法一: sqlacodegen命令

查询资料,首先看到的是使用sqlacodegen方法,建议参考博客:起初使用这种方法在本地确实可以方便的生成所有实体类,并生成model文件,然后获取文件中的所有class,最后我们就可以通过表名获取到对应的实体类,然后进行ORM操作

def get_classes(module_name=storage.db_models) -> dict:
# 获取db_models文件 中所有类对象
    classes = []
    table = {}
    file = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + '/storage/' + 'db_models.py'
    if not os.path.exists(file):
        return table
    ret = inspect.getmembers(module_name, inspect.isclass)

    try:
        for name, class_ in ret:
            classes.append(class_)
            if '__tablename__' in dir(class_):
                table[class_.__tablename__] = class_
    except Exception as e:
        logging(e, exc_info=True)
    return table

缺点:

  1. 通过ip+port的形式连接数据库,在本地可操作,线上不一定会被允许,例如我们公司不允许使用ip+port的形式连接,封装了自己的mysql库,导致上线失败
  2. 需要定时的去运行sqlacodegen命令,保证获取的model文件是最新的

方法二: SQLAlchemy 反射已有表

强烈推荐使用这种方法

真是宝藏方法,解决了很大一麻烦,具体可以参考这篇博客,里面有三种方法https://www.jianshu.com/p/f6527ab2428d, 下面展示自己写的伪代码:亲测是有效的,可以动态感知数据表结构变化

    def create_model(self):
        """反射数据表为实体类"""
        engine = SQLAlchemyEngine()._engine  # 创建数据库引擎,可以根据具体情况操作,不用担心线上线下环境影响,和普通连接数据库创建引擎方法相同
        Base = automap_base()
        Base.prepare(engine, reflect=True)
        Base.classes.keys()  # 获取所有的对象名
        return Base.classes
    def test():
    	table = self.create_table()
    	table_name = 'test_example‘ # 数据库表名
    	model = table[table_name]
    	ret = s.query(model).filter_by(**condition).update(data)  # 进行ORM操作

通过这次事件,以后即使不做DAL层,只写业务代码,也会选择这种方法,不会呆板地维护自己的model类了,虽然对于熟悉业务的个人来说改造比较方便成本不大,但是如果进行业务交接就很麻烦了,保持一个原则:能动态感知的尽量使用动态方法感知,能少改动代码的少改动,能不重新上线的不上线。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值