【SQLAlchemy】flushとcommitの違い
session.commit()
をすると、session.flush()
も一緒に実行するらしくcommit()
だけでもいいんじゃないかと思ってた。
だが、commit()
だけだと、うまくいかないケースがあったので備考録として残す。
ざっくりというと、思った通りの順番でadd
して登録したつもりでもcommit()
の時にDBへ送られるsqlの順番は保証できないよというお話
commitとは~、flushとは~と言葉で説明してもわけわからんので、flushを気にする必要があるパターン例でみればわかる気がするので以下掲載
commit
については、DB関連でいっぱい説明あると思うので割愛
- flushを意識しないでも問題ないパターン
- 適切な順番でinsertする必要がある場合(flushする必要あり)
- コミット前のinsertデータに対してselectしたい場合(flushする必要あり)
flushを意識しないでも問題ないパターン
# マスタに未登録の商品のみ登録する product_id = info.get('product_id') product_name = info.get('product_name') price = info.get('price') if not db.session.query(Products).filter(Products.product_id == product_id ).first(): # 商品マスタ登録 product = Products() product.product_id = product_id product.product_name= product_name product.price = price db.session.add(product) db.session.commit()
- すでにcommit済みのデータをselectして、利用したりする
- insert対象が1テーブルだけ、や任意の順番でinsertされようが問題ない 場合など
適切な順番でinsertする必要がある場合(flushする必要あり)
外部キーが設定してある場合など。マスタテーブルのほうにレコードがないと、制約違反で落ちる
product_id = info.get('product_id') product_name = info.get('product_name') price = info.get('price') category_id = info.get('category_id') category_name = info.get('category_name') # カテゴリマスタ登録 category = Categories() category.category_id = category_id category.category_name = category_name db.session.add(category) db.session.flush() # DBに上のSQLを投げたよーという通知 # 商品マスタ登録 product = Products() product.product_id = product_id product.product_name= product_name product.price = price product.category_id = category_id db.session.add(product) db.session.commit()
※ Product.category_id には、Category.category_idへの外部キー制約がついている想定です。
コミット前のinsertデータに対してselectしたい場合(flushする必要あり)
検証はしていないけど、おそらくこのパターンもflushは必要。実際は、何らかのカウントしたり、集計した結果に対して実行はするのだろうけど簡略化のためキー検索を例にしている
# 商品マスタ登録 product = Products() product.product_id = product_id product.product_name= product_name product.price = price product.category_id = category_id db.session.add(product) db.session.flush() # commit前のinsert情報に対して修正する if db.session.query(Products).filter(Products.product_id == product_id ).first(): # ~何らかの処理~(insert結果がおかしかったら,rollbackなどの処理とか) # 登録時にflushしていないと、レコードを取得できない db.session.commit()