Атрибут expire_on_commit
Атрибут expire_on_commit класса Session
управляет поведением объектов после
завершения транзакции методом commit.
По умолчанию атрибут равен True, что означает
устаревание всех объектов сессии после коммита.
При следующем обращении к атрибутам объекта
SQLAlchemy автоматически загружает актуальные
данные из базы данных. Если установить значение
False, объекты останутся в текущем состоянии
после коммита без дополнительных запросов к базе.
Синтаксис
session.expire_on_commit = True
session.expire_on_commit = False
Пример
Давайте создадим сессию с параметром
expire_on_commit равным True
и посмотрим, как объект устаревает после коммита:
from sqlalchemy import create_engine, String
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, Session
class Base(DeclarativeBase):
pass
class Article(Base):
__tablename__ = 'articles'
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str] = mapped_column(String(100))
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine, expire_on_commit=True) as session:
article = Article(title='article')
session.add(article)
session.commit()
print(article.title)
Результат выполнения кода:
"article"
После коммита объект article был устаревлен,
но при обращении к атрибуту title SQLAlchemy
автоматически выполнила запрос к базе данных
для загрузки актуального значения.
Пример
Давайте установим expire_on_commit равным
False и проверим, что объект не устаревает
после коммита:
from sqlalchemy import create_engine, String
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, Session
class Base(DeclarativeBase):
pass
class Article(Base):
__tablename__ = 'articles'
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str] = mapped_column(String(100))
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
with Session(engine, expire_on_commit=False) as session:
article = Article(title='article')
session.add(article)
session.commit()
print(article.title)
print(article in session)
Результат выполнения кода:
"article"
True
Объект остался привязанным к сессии и сохранил свои атрибуты без дополнительного запроса к базе данных.
Пример
Давайте рассмотрим разницу в количестве
SQL-запросов при expire_on_commit=True
и expire_on_commit=False:
from sqlalchemy import create_engine, String, event
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, Session
class Base(DeclarativeBase):
pass
class Article(Base):
__tablename__ = 'articles'
id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str] = mapped_column(String(100))
engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)
query_count = 0
@event.listens_for(engine, "before_cursor_execute")
def count_queries(conn, cursor, statement, parameters, context, executemany):
global query_count
query_count += 1
with Session(engine, expire_on_commit=True) as session:
article = Article(title='article')
session.add(article)
session.commit()
query_count = 0
print(article.title)
print(f"Queries with expire_on_commit=True: {query_count}")
with Session(engine, expire_on_commit=False) as session:
article = Article(title='article')
session.add(article)
session.commit()
query_count = 0
print(article.title)
print(f"Queries with expire_on_commit=False: {query_count}")
Результат выполнения кода:
"article"
"Queries with expire_on_commit=True: 1"
"article"
"Queries with expire_on_commit=False: 0"
При expire_on_commit=True после коммита
выполняется дополнительный запрос для загрузки
атрибутов объекта, а при False - нет.