[Python] ORM数据库SQLAlchemy的使用示例

SQLAlchemy 是 Python 中一个非常流行的对象关系映射(ORM)库,用于简化数据库操作。它提供了一种灵活的方式,让开发者可以用 Python 代码与数据库交互,而无需直接编写大量的 SQL 语句。

简单来说,SQLAlchemy 的主要特点包括:

  1. ORM 功能:可以将数据库表映射为 Python 类,把表中的行当作对象来操作。这样,你可以用面向对象的方式处理数据,比如创建、查询、更新和删除记录。
  2. 数据库抽象:支持多种数据库(如 SQLite、MySQL、PostgreSQL 等),只需稍作调整就能切换数据库类型,而不用重写大部分代码。
  3. 灵活性:除了 ORM,它还提供了底层的 SQL 表达式语言,允许你直接编写复杂的 SQL 查询,适合需要精细控制的场景。
  4. 会话管理:通过 Session 对象管理数据库连接和事务,确保操作高效且安全。
举个简单的例子:
复制代码
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

# 创建数据库连接
engine = create_engine('sqlite:///example.db')
Base = declarative_base()

# 定义一个模型
class User(Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    name = Column(String)

# 创建表
Base.metadata.create_all(engine)

# 创建会话
Session = sessionmaker(bind=engine)
session = Session()

# 添加数据
new_user = User(name='Alice')
session.add(new_user)
session.commit()

# 查询数据
user = session.query(User).filter_by(name='Alice').first()
print(user.name)  # 输出: Alice
复制代码

在 SQLAlchemy 中,创建表通常是通过定义模型类并结合 Base.metadata.create_all() 方法完成,定义的模型类继承Base,在执行创建表语句Base.metadata.create_all(engine)之前,只要模型类被引入(import)就会被创建。

 

问题一:解决查询的数据在脱离会话(Session)后不能正常使用问题。

当你从会话中查询数据(比如 session.query(User).first()),返回的对象通常绑定到该会话。如果会话关闭(session.close())或提交(session.commit())后,对象可能进入“过期”状态。访问它的属性时,可能会触发“DetachedInstanceError”,因为 SQLAlchemy 试图通过已关闭的会话加载数据。

解决方法

  • 使用 expunge:在会话关闭前,可以用 session.expunge(obj) 将对象从会话中分离,这样它就不再依赖会话,可以独立使用。
  • 关闭自动过期:设置 expire_on_commit=False(在 sessionmaker 中),这样提交后对象不会过期,可以继续使用。

我的项目中使用了上面两个方法。

 

问题二:解决多线程共用一个会话,保存数据时混乱问题。

在 SQLAlchemy 中,多线程共用一个会话(Session)可能会导致数据混乱,因为会话默认不是线程安全的。每个线程可能同时操作同一个会话对象,引发竞争条件、数据覆盖或事务冲突等问题。为了解决这个问题,可以采取以下方法:

  • 为每个线程创建独立的 Session 对象,避免共享同一个会话。
  • 使用线程局部会话(Scoped Session)(推荐):SQLAlchemy 提供了 scoped_session,它利用 Python 的 threading.local() 确保每个线程有独立的会话实例,但全局共用一个会话工厂。
  • 数据库连接池管理SQLAlchemy 的引擎自带连接池(默认使用 QueuePool),可以支持多线程访问数据库。但会话本身仍需独立管理,连接池只负责底层的数据库连接复用。

我的项目中,使用第三种方案, QueuePool线程池+会话管理。

 

问题三:修改模型类同步更新数据库表结构问题。

在 SQLAlchemy 中,当你修改了模型类(比如添加、删除字段或更改约束)后,数据库表结构并不会自动同步更新,因为 SQLAlchemy 本身不提供内置的表结构迁移功能。不过,可以通过以下方法解决这个问题:

  • 手动更新表结构修改模型类后,手动编写并执行 SQL 语句(如 ALTER TABLE)来调整数据库表结构。
  • 使用 Alembic 进行数据库迁移。
  • 重建表(不推荐)。

我的项目中,使用创建临时表,再重建表逐条恢复数据,仅支持SQLite数据库。

项目git路径:https://gitee.com/Pumbaa_Peng/pp-spyder.git

posted @   孤独成派  阅读(29)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
点击右上角即可分享
微信分享提示