对SQLAlchemy中的add()、flush()、commit()操作理解

文章目录


问题

下面是一个接口测试文件:

from applications.models.ri_zhi.gong_zuo_ri_zhi import GongZuoRiZhi
from applications.models.system.models import RenYuanDengLu, ZuZhiXinXi, RenYuanXinXi


class TestGongZuoWanChengQueRen:

    def test_get_zuo_ye_wan_cheng_qing_ren_yuans(self, client, db, setup_before_test):
        ren_yuan_deng_lu1 = RenYuanDengLu(ren_yuan_name='张三')
        ren_yuan_deng_lu2 = RenYuanDengLu(ren_yuan_name='李四')
        db.session.add(ren_yuan_deng_lu1)
        db.session.add(ren_yuan_deng_lu2)
        db.session.flush()
        ren_yuan_xin_xi1 = RenYuanXinXi(
            ren_yuan_id=ren_yuan_deng_lu1.id)
        ren_yuan_xin_xi2 = RenYuanXinXi(
            ren_yuan_id=ren_yuan_deng_lu2.id)
        # 01
        zuo_ye_wan_cheng_qing_ren_yuans1 = GongZuoRiZhi(
            gong_zuo_ren_id=1,
            gong_zuo_jue_se='审批文件',
            biao_dan_bian_hao='1223',
            gong_zuo_kai_shi_shi_jian='2020-01-01',
            gong_zuo_jie_shu_shi_jian='2020-01-11',
        )
        # 02
        zuo_ye_wan_cheng_qing_ren_yuans2 = GongZuoRiZhi(
            gong_zuo_ren_id=2,
            gong_zuo_jue_se='主办人',
            biao_dan_bian_hao='1223',
            gong_zuo_kai_shi_shi_jian='2020-01-01',
            gong_zuo_jie_shu_shi_jian='2020-01-11',
        )

        db.session.add(zuo_ye_wan_cheng_qing_ren_yuans1)
        db.session.add(zuo_ye_wan_cheng_qing_ren_yuans2)
        db.session.add(ren_yuan_xin_xi1)
        db.session.add(ren_yuan_xin_xi2)
        db.session.flush()
        db.session.commit()

        response1 = client.get(
            '/zuo_ye_gong_zuo_wan_cheng_qing_kuang_que_ren/get_zuo_ye_wan_cheng_qing_kuang_que_ren_ren_yuan/?tong_ji_kai_shi_shi_jian=2019-01-03&tong_ji_jie_shu_shi_jian=2021-01-05&type=流程')
        assert response1.status_code == 200
        results1 = response1.json['data']
        print(results1)
        # assert len(results1) == 1

        # 验证第一个元素的内容
        assert results1[0]['id'] == 1
        assert results1[0]['name'] == '张三'

        response2 = client.get(
            '/zuo_ye_gong_zuo_wan_cheng_qing_kuang_que_ren/get_zuo_ye_wan_cheng_qing_kuang_que_ren_ren_yuan/?tong_ji_kai_shi_shi_jian=2019-01-03&tong_ji_jie_shu_shi_jian=2021-01-05&type=作业')
        assert response2.status_code == 200
        results2 = response2.json['data']
        print(results2)
        # assert len(results2) == 1

        # 验证第一个元素的内容
        assert results2[0]['id'] == 2
        assert results2[0]['name'] == '李四'

着重看#01部分的测试用例中的这几行代码:

zuo_ye_wan_cheng_qing_ren_yuans1 = GongZuoRiZhi(
    gong_zuo_ren_id=1,
    gong_zuo_jue_se='审批文件',
    biao_dan_bian_hao='1223',
    gong_zuo_kai_shi_shi_jian='2020-01-01',
    gong_zuo_jie_shu_shi_jian='2020-01-11',
)

来看gong_zuo_ren_id这个属性,在我的数据库表关系中,gong_zuo_ren_id是一个外键,指向RenYuanXinXi表的id,由于我在这块代码之前已经在RenYuanXinXi插入了数据,数据表中的id是自动递增的。理论上说,上面的代码中gong_zuo_ren_id=1可以改成gong_zuo_ren_id=ren_yuan_xin_xi1.id,但是测试不通过,数据库中,没有返回符合条件的数据。

经过排查发现,问题出在add()flush()这两个函数上,我在创建完ren_yuan_xin_xi1之后,并没有进行add()flush()操作,这就导致当前会话的数据库中,并没有这条数据,紧接着我在ren_yuan_xin_xi1.id的时候,自然不会有id的值让我拿到。

代码应该修改成下面这样:

        ren_yuan_deng_lu1 = RenYuanDengLu(ren_yuan_name='张三')
        ren_yuan_deng_lu2 = RenYuanDengLu(ren_yuan_name='李四')
        db.session.add(ren_yuan_deng_lu1)
        db.session.add(ren_yuan_deng_lu2)
        db.session.flush()
        ren_yuan_xin_xi1 = RenYuanXinXi(
            ren_yuan_id=ren_yuan_deng_lu1.id)
        ren_yuan_xin_xi2 = RenYuanXinXi(
            ren_yuan_id=ren_yuan_deng_lu2.id)
        db.session.add(ren_yuan_xin_xi1)
        db.session.flush()
        # 01
        zuo_ye_wan_cheng_qing_ren_yuans1 = GongZuoRiZhi(
            gong_zuo_ren_id=ren_yuan_xin_xi1.id,
            gong_zuo_jue_se='审批文件',
            biao_dan_bian_hao='1223',
            gong_zuo_kai_shi_shi_jian='2020-01-01',
            gong_zuo_jie_shu_shi_jian='2020-01-11',
        )

#02测试用例同理。

涉及技术点

关于add()fulsh()commit()操作的作用:

db.session.add()db.session.flush()db.session.commit() 是 SQLAlchemy 中常用的数据库操作方法,它们通常结合使用来管理会话(Session)中的数据库事务。

  1. db.session.add()
    • 用于将新创建或修改后的实体对象添加到当前会话中。
    • 只是将对象添加到会话的临时缓存中,并不会立即执行数据库操作。
    • 在使用 add() 方法后,可以继续对对象进行修改,直到调用 flush()commit() 执行实际数据库操作。
  2. db.session.flush()
    • 将当前会话中所有未提交的数据库操作(插入、更新、删除等)发送到数据库服务器执行。
    • flush()方法通常在以下情况下使用:
      • 当需要在后续代码中获取插入记录的自增 ID(例如,MySQL 中的 AUTO_INCREMENT)时,可以在 flush() 后立即获得 ID。
      • 当需要立即检查数据库操作是否成功或是否有错误时,可以在 flush() 后查看数据库执行结果。
  3. db.session.commit()
    • 将当前会话中的所有数据库操作提交到数据库服务器。
    • commit() 方法将会话中的所有操作一起作为一个事务提交到数据库。
    • 提交后,所有之前的 flush() 操作将永久生效,且数据库事务完成。

通常,数据库操作的基本流程是:

  1. 使用 add() 将实体对象添加到会话中,可以在此阶段进行实体对象的初始化和修改。
  2. 使用 flush() 提交之前的数据库操作,以便获取自增 ID 或检查执行结果。
  3. 使用 commit() 最终将所有操作提交到数据库,实现持久化存储。

需要注意的是,在使用 commit() 提交事务后,会话将被清理,所有之前添加的对象和更改都会失去跟踪。所以,在一个会话中,通常只需要调用一次 commit()。如果希望在多个事务中执行数据库操作,可以创建多个会话,每个会话独立管理自己的事务。

猜你喜欢

转载自blog.csdn.net/weixin_45605541/article/details/131826046