はじめに
データベースにデータを追加したり削除したりといった操作をする場合、たいていは複数の操作をまとめて実行することが多い。
例えば、あるネットショップのデータベースが「商品テーブル」「注文テーブル」「注文詳細テーブル」で構成されているとする。ある商品の注文が入ったら「注文詳細テーブル」に注文された商品や数量などを保存すると同時に、「商品テーブル」の在庫数を減らさなければならない。これがどれかの処理でエラーが発生し、途中で止まってしまったらどうなるか。注文は入ったけど在庫数が減らないなんていう事態が発生してしまう。これは絶対に避けたい。
だからデータベースの処理は「すべての正常に変更し"確定"」か、「一個でもエラーが発生したらすべての変更を"破棄"」のどっちかでなけれなならない。このような処理をトランザクション処理という。
実装方法
流れ
トランザクション処理は下記により実装する。
with db.session.begin(subtransactions=True): # データベースへの分割不可な一連処理 db.session.commit()
以前の記事を参考にデータベースを作成し、操作するプログラムを実装する。
階層構造
MODEL_EXAM ├─app.py └─model_exam.sqlite
コード
# app.py import os from flask import Flask from flask_sqlalchemy import SQLAlchemy app = Flask(__name__) basedir = os.path.abspath(os.path.dirname(__name__)) app.config['SECRET_KEY'] = 'mysecretkey' app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'model_exam.sqlite') app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True db = SQLAlchemy(app) class Members(db.Model): __tablename__ = 'members' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.Text) age = db.Column(db.Integer) comment = db.Column(db.Text) def __init__(self, name, age, comment): self.name = name self.age = age self.comment = comment db.create_all() # テーブルの作成 # トランザクション処理 with db.session.begin(subtransactions=True): # データベースへの分割不可な一連処理 new_member = Members("john", 29, "aaaabbbb") db.session.add(new_member) db.session.commit()