SQLAlchemyで全てのリレーションシップにデフォルトでロード戦略を設定する方法
SQLAlchemyは、Pythonでオブジェクト関係マッピング(ORM)を行うためのライブラリです。ORMを使用すると、データベースのテーブルとオブジェクトを相互に関連付けることができます。
デフォルトでは、SQLAlchemyは関係を遅延読み込みします。これは、関連するオブジェクトが実際に必要になるまで、データベースから読み込まれないことを意味します。これはパフォーマンスを向上させるのに役立ちますが、コードがより複雑になる可能性があります。
すべての関係にデフォルトでロード戦略を設定することで、コードをよりシンプルにすることができます。
ロード戦略
SQLAlchemyは、関係をロードするためにいくつかの戦略を提供します。
- 遅延読み込み:関連するオブジェクトが実際に必要になるまで、データベースから読み込まれません。
- Eager読み込み:関連するオブジェクトは、親オブジェクトが読み込まれるときにデータベースから読み込まれます。
- SelectIn:関連するオブジェクトは、親オブジェクトが読み込まれるときに、SELECTクエリの一部としてデータベースから読み込まれます。
- JoinedSubquery:関連するオブジェクトは、親オブジェクトが読み込まれるときに、JOINEDサブクエリを使用してデータベースから読み込まれます。
設定方法
すべての関係にデフォルトでロード戦略を設定するには、relationship()
メソッドの lazy
引数を使用します。
from sqlalchemy import Column, Integer, ForeignKey, relationship
class Parent(Base):
__tablename__ = 'parent'
id = Column(Integer, primary_key=True)
children = relationship('Child', lazy='eager')
class Child(Base):
__tablename__ = 'child'
id = Column(Integer, primary_key=True)
parent_id = Column(Integer, ForeignKey('parent.id'))
この例では、Parent
クラスの children
リレーションシップは、デフォルトでEager読み込みされます。
すべての関係にデフォルトでロード戦略を設定する他にも、いくつかの方法があります。
relationship()
メソッドのdefault_lazy
引数を使用するMapper
クラスのdefault_lazy
属性を設定するconfigure_mappers()
関数を使用する
from sqlalchemy import Column, Integer, ForeignKey, relationship
class Parent(Base):
__tablename__ = 'parent'
id = Column(Integer, primary_key=True)
children = relationship('Child', lazy='eager')
class Child(Base):
__tablename__ = 'child'
id = Column(Integer, primary_key=True)
parent_id = Column(Integer, ForeignKey('parent.id'))
# すべての関係をEager読み込みに設定
Base.metadata.create_all(engine)
parent = Parent()
child1 = Child()
child2 = Child()
parent.children.append(child1)
parent.children.append(child2)
session.add(parent)
session.commit()
# 子オブジェクトはEager読み込みされる
session.query(Parent).first()
# すべての関係をSelectIn読み込みに設定
Base.metadata.drop_all(engine)
class Parent(Base):
__tablename__ = 'parent'
id = Column(Integer, primary_key=True)
children = relationship('Child', lazy='selectin')
class Child(Base):
__tablename__ = 'child'
id = Column(Integer, primary_key=True)
parent_id = Column(Integer, ForeignKey('parent.id'))
Base.metadata.create_all(engine)
parent = Parent()
child1 = Child()
child2 = Child()
parent.children.append(child1)
parent.children.append(child2)
session.add(parent)
session.commit()
# 子オブジェクトはSelectIn読み込みされる
session.query(Parent).first()
すべての関係にデフォルトでロード戦略を設定する他の方法
ここでは、他の方法を紹介します。
relationship()
メソッドの default_lazy
引数を使用して、すべての関係にデフォルトでロード戦略を設定することができます。
from sqlalchemy import Column, Integer, ForeignKey, relationship
class Parent(Base):
__tablename__ = 'parent'
id = Column(Integer, primary_key=True)
class Child(Base):
__tablename__ = 'child'
id = Column(Integer, primary_key=True)
parent_id = Column(Integer, ForeignKey('parent.id'))
# すべての関係をEager読み込みに設定
Base.relationship(default_lazy='eager')
parent = Parent()
child1 = Child()
child2 = Child()
parent.children.append(child1)
parent.children.append(child2)
session.add(parent)
session.commit()
# 子オブジェクトはEager読み込みされる
session.query(Parent).first()
from sqlalchemy import Column, Integer, ForeignKey, relationship, Mapper
class Parent(Base):
__tablename__ = 'parent'
id = Column(Integer, primary_key=True)
class Child(Base):
__tablename__ = 'child'
id = Column(Integer, primary_key=True)
parent_id = Column(Integer, ForeignKey('parent.id'))
# すべての関係をEager読み込みに設定
Mapper.default_lazy = 'eager'
parent = Parent()
child1 = Child()
child2 = Child()
parent.children.append(child1)
parent.children.append(child2)
session.add(parent)
session.commit()
# 子オブジェクトはEager読み込みされる
session.query(Parent).first()
configure_mappers()
関数を使用して、すべての関係にデフォルトでロード戦略を設定することができます。
from sqlalchemy import Column, Integer, ForeignKey, relationship, configure_mappers
class Parent(Base):
__tablename__ = 'parent'
id = Column(Integer, primary_key=True)
class Child(Base):
__tablename__ = 'child'
id = Column(Integer, primary_key=True)
parent_id = Column(Integer, ForeignKey('parent.id'))
# すべての関係をEager読み込みに設定
configure_mappers(lambda mapper: mapper.default_lazy='eager')
parent = Parent()
child1 = Child()
child2 = Child()
parent.children.append(child1)
parent.children.append(child2)
session.add(parent)
session.commit()
# 子オブジェクトはEager読み込みされる
session.query(Parent).first()
sqlalchemy