6
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

SQLAlchemyのautoflushについて

Last updated at Posted at 2019-05-12

概要

SQLAlchemyのautoflushについて理解できてなかったので調査しました。

調査した時の各バージョン

  • SQLAlchemy : 1.3.3
  • MySQL : 8.0.16

modelの作成

シンプルなuser_listテーブルを作成しこのテーブルをSQLAlchemyから操作することでautoflushの挙動を確認します。

model.py
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String

Base = declarative_base()

class User(Base):
    __tablename__ = 'user_list'
    id = Column('id', Integer, primary_key=True)
    name = Column('name', String(100))

autoflushの検証①(autoflush=True)

autoflushをTrueにして動作検証してみます。autoflushの影響があるのはSessionクラスの"add"、"delete"メソッドを使った時やモデルのプロパティに書き込みをした時(update)ですが、とりえあずaddメソッドで検証してみます。

main.py
from sqlalchemy.orm import Session
from model import User

# ~ 中略 ~

session = Session(
    bind = ENGINE,
    autocommit = False,
    autoflush = True)

#1 user_listテーブルのレコード数確認
user_list = session.query(User)
print(user_list.count()) # ⇒ "0"出力

#2 1レコード追加
user = User(id = 1, name = 'hoge')
session.add(user)

#3 user_listテーブルのレコード数確認
print(user_list.count()) # ⇒ "1"出力

上記のコードを実行した場合、autoflush=Trueにしていると自動でinsert文が実行されるので#3の時点で"1"と出力されます。但し、実際にinsert文が実行されるタイミングは#3の"user_list.count()"が実行された時です。(この挙動はflushの処理をできるだけ遅延させる為、だろうか?)

autoflushの検証②(autoflush=False、明示的にflush実行)

autoflushをFalseにして明示的にflushメソッドを呼ぶパターンで動作検証してみます。

main.py
from sqlalchemy.orm import Session
from model import User

# ~ 中略 ~

session = Session(
    bind = ENGINE,
    autocommit = False,
    autoflush = False)

#1 user_listテーブルのレコード数確認
user_list = session.query(User)
print(user_list.count()) # ⇒ "0"出力

#2 1レコード追加
user = User(id = 1, name = 'hoge')
session.add(user)
session.flush() # 明示的にflushメソッドを実行(insert文が実行される)

#3 user_listテーブルのレコード数確認
print(user_list.count()) # ⇒ "1"出力

上記のコードを実行した場合、autoflush=Falseではあるが明示的に"session.flush()"を実行しているので、この場合も#3の時点で"1"と出力されます。但し、実際にinsert文が実行されるタイミングはautoflush=Trueの時と異なり"session.flush()"の時点です。

autoflushの検証③(autoflush=False、flush無し)

autoflushをFalseにしてflushメソッドを呼ばないパターンで動作検証してみます。

main.py
from sqlalchemy.orm import Session
from model import User

# ~ 中略 ~

session = Session(
    bind = ENGINE,
    autocommit = False,
    autoflush = False)

#1 user_listテーブルのレコード数確認
user_list = session.query(User)
print(user_list.count()) # ⇒ "0"出力

#2 1レコード追加
user = User(id = 1, name = 'hoge')
session.add(user)

#3 user_listテーブルのレコード数確認
print(user_list.count()) # ⇒ "0"出力

上記のコードを実行した場合、autoflush=Falseで"session.flush()"も実行していないのでinsert文は実行されず、#3の時点ではレコードが追加されていないので"0"が出力されます。ではこの場合は"session.add()"がなかったことになるのかというとそういうわけでもなく、最終的に"session.commit()"してやればそのタイミングでinsert文は実行されます。

autoflushはTrue、Falseのどちらが良いか?

基本的にautoflush=Trueにしておいたほうがうっかりミスも発生せずコードもシンプルになり良さそうです。Sessionクラスのデフォルト値もautoflush=Trueですし。逆にautoflush=Falseにしたほうが良い場合が思いつかない。。(SQL実行のタイミングを明示的にしたい場合とか?)

6
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?