【SQLAlchemy】第三篇——ORM编程

ORM技术允许开发者用面向对象的方式操作数据库,如Python的SQLAlchemy库。通过定义类来表示数据库表,类的属性映射到表的字段,实例代表表的行。文章介绍了如何创建表、插入数据、查询、修改和删除数据,以及如何自动映射数据库中的已有表到ORM类。
摘要由CSDN通过智能技术生成

可以熟练使用面向对象编程语言——如Python——的人,一定会非常容易理解关系型数据库的设计原则。以MySQL为例,如果用Python中的一个类来表示数据库中的一张表,用类的属性来表示表的字段,那么类的一个实例就表示表中的一行数据。

按照这种方式,完全可以将表用类来表示。自然地,我们会想,既然数据表可以被映射成类,那么对类的操作是不是也可以同步到相应的表呢?答案是肯定的,这就是所谓的ORM技术。

ORM 是对象关系映射(Object-Relational Mapping)的缩写,它是一种软件开发技术,用于将面向对象的编程语言中的对象与关系数据库中的数据进行映射。ORM 通过将关系数据库中的表和列转换成面向对象编程语言中的类和属性,使得开发人员可以用面向对象的方式来操作数据库,而不必关心底层的 SQL 查询语句和数据库操作细节。ORM 技术旨在提高开发效率,降低代码维护成本,同时也可以减少 SQL 注入等安全问题的出现。常见的 ORM 框架有 Hibernate、Django ORM、SQLAlchemy 等。

——来自ChatGPT

1、利用类定义表并写入数据

1.1 建表

利用ORM技术,可以通过在Python中定义类来定义数据表:

from sqlalchemy import Column, Integer, String, ForeignKey, create_engine
from sqlalchemy.orm import declarative_base

Base = declarative_base()
engine = create_engine('mysql+pymysql://root:123456@127.0.0.1:3306/test')


class User(Base):
    __tablename__ = "user_account"
    id = Column(Integer, primary_key=True)
    name = Column(String(30))
    fullname = Column(String(30))

    def __repr__(self):
        return f"User(id={self.id!r}, name={self.name!r}, fullname={self.fullname!r})"


class Address(Base):
    __tablename__ = "address"
    id = Column(Integer, primary_key=True)
    email_address = Column(String(30), nullable=False)
    user_id = Column(Integer, ForeignKey("user_account.id"))

    def __repr__(self):
        return f"Address(id={self.id!r}, email_address={self.email_address!r})"


Base.metadata.create_all(engine)

关注类的定义代码不难看出,表结构是通过类属性定义的。其中,__tablename__是一个特殊的属性,用于表示该类所对应的表的名称。表的其他字段名称及其约束通过实例化Column为一个变量的方式进行声明。在实例化时,可以对字段的数据类型、长度、是否为主键等进行限制。

类中还定义了两张表的关系。在此处的情境中,一个用户被认为可以拥有多个邮件地址,而一个邮件地址只能属于一个用户,因此,它们之间的关系是“一对多”的。在address表中,定义的user_id字段是引用的主表user_account的主键id字段。

在定义指代表的类的时,主要它们都需要继承自Base——一个具有声明性质的类。只有继承自Base的类才能用上面的写法定义表结构。最后,通过Base.metadata.create_all(engine)来将在Python中定义好的类映射成表并写入数据库中。

1.2 插入数据

通过ORM方法来与数据库进行交互时用的最多的是一种被称为Session的对象。对于熟悉PyMySQL的读者而言,它非常类似于后者的Connection。实际上,Session对象与各种数据库进行交互时,就是通过各个驱动包的Connection(有可能是其他的名字)来实现的。

首先,通过实例化已定义的类来构造需要写入数据表中的数据行:

user1 = User(id=1, name='Everill', fullname='Everill Glen')
user2 = User(id=2, name='Hughes', fullname='Hughes Adnan')
addr1 = Address(id=1, email_address='everillglen1@example.com', user_id=1)
addr2 = Address(id=2, email_address='everillglen2@example.com', user_id=1)
addr3 = Address(id=3, email_address='hughesadnan@example.com', user_id=2)

这里简单地创建了两个User实例和三个Address实例。至此,它们还只是Python中的对象,与数据库还没有建立联系。为了将它们写入数据表,需要用到Session。通过以下方式,可以创建一个Session对象:

from sqlalchemy.orm import Session
session = Session(engine)

调用Sessionadd()方法,可以将一个实例“绑定”到session上。这里有5个实例,为简单起见可以调用Sessionadd_all()将这些实例一次性绑定到session上:

session.add_all([user1, user2, addr1, addr2, addr3])

上述“绑定”的过程,实际上就是Session对象积累变更的过程。出于效率和其他因素的考虑,除非用户发出明确地指令,SQLALchemy不会将这些变更自动同步到数据库。

通过调用Sessionflush()方法,可以将积累的变更同步到数据库:

session.flush()

调用flush()实际上是创建一个事务以将变更对应的SQL发送到数据库服务器进行执行。如果一切顺利,最后还需要调用commit()方法来真正完成上述事务。

当然,在实际中,可以直接调用commit()方法,SQLALchemy会自动进行flush。

1.3 按主键查询

既然UserAddress已经和数据库中的user_accountaddress表相对应,那么当然可以通过表的主键来查询特定的实例:

session.get(User, 1)

1.4 修改实例

user = session.get(User, 1)
user.fullname = 'Everill Green'

上述两行代码将id为1的实例的fullname属性进行了修改。与插入数据的过程类似,这种修改此时仍积累在Session对象中,并未同步到数据库。

Session对象通过一个集合来保存这些变更了的实例:

user in session.dirty
# True

再调用commit()方法后,上述语句返回False,表明user不存在待提交的变更。

如果不想将这些变更提交到数据库,则调用rollback()方法:

session.rollback()
session.dirty  # 回滚后,变更集合为空

1.5 删除实例

类似地,先获取实例,再调用delete()方法,则可以删除实例:

user = session.get(User, 1)
session.delete(user)

要想删除生效,仍需要调用commit()方法。

至此,可以总结发现,通过Session对象对数据库进行增删改查等基本操作时,SQLALchemy都会将其转化为对应的SQL并开启一个事务进行执行。若要执行生效,需要显示地进行提交(commit());若要进行回滚,则执行rollback()

2、获取已有的数据表

很多时候,我们需要做的是对已经存在于数据库中的表进行增删改查等操作。显然,应对这个问题时,我们希望将数据表批量映射为Python中的类,而不是从头将它们在Python中定义一遍。

在SQLALchemy中,我们可以使用automap_base()函数可以自动将数据库中的表映射为ORM类:

from sqlalchemy.ext.automap import automap_base

# 自动加载所有现有数据表并创建ORM映射对象
Base = automap_base()
Base.prepare(engine, reflect=True)

# 获取ORM映射对象
User = Base.classes.user_account
Address = Base.classes.address

至此,便可以通过第一部分所说的方法来对数据表进行操作了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

芳樽里的歌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值