flask-sqlalchemyの用法研究について

3522 ワード

最近flaskのsqlalchemyを使って、flaskがsqlalchemyに対していくつかパッケージをしたため、自分自身がsqlalchemyに対しても熟知していないことを加えて、使い方の上で多くの回り道をしました.
sqlalchemyのソースコードを研究する時間がないので、簡単に使い方をテストするしかありません.
1、flask-sqlalchemyはスレッドが安全である
具体的には文章を参考にすることができるhttps://blog.csdn.net/luffyser/article/details/89380186
 
2、毎回クエリーが終わったら、commitを覚えておいてください.そうしないと、接続プールが占有されます.
ローカルで簡単なテストをしましたが、単一のクエリーリクエストが完了し、commitしなければ、何度もリクエストを続け、requestを開始すると応答がなく、データベース接続プールが解放されず、占有されていると推測されます.リクエスト・データベースが一時停止し、responseが発生しません.
リクエストが完了するたびに、この問題を直接commitで解決できます.  
    def queryLast(cls):
        try:
            ret = db.session.query(cls).order_by(cls.version.desc()).first()
       #db.session.expunge(ret) db.session.commit() except: db.session.rollback() ret = None return ret

 
3.ただし、Commitを使用すると、クエリの結果がキャッシュから消去される可能性があり、クエリの結果を使用するオブジェクトを使用すると、接続クエリが再確立されます.このため、上記の接続プールが枯渇するという問題も発生します.
下のアイコンの黄色いログから、commit後、返されたクエリー結果を使用すると、クエリータスクが実行され、結果が返されます.my god!
2019-12-10 12:31:21,650 INFO sqlalchemy.engine.base.Engine BEGIN (implicit)
2019-12-10 12:31:21,651 INFO sqlalchemy.engine.base.Engine SELECT appversion.id AS appversion_id, appversion.version AS appversion_version, appversion.`appUrl` AS `appversion_appUrl`, appversion.des AS appversion_des, appversion.`createTime` AS `appversion_createTime`, appversion.`lastModiftyTime` AS `appversion_lastModiftyTime`, appversion.type AS appversion_type 
FROM appversion ORDER BY appversion.version DESC 
 LIMIT %s
2019-12-10 12:31:21,651 INFO sqlalchemy.engine.base.Engine (1,)
2019-12-10 12:31:21,661 INFO sqlalchemy.engine.base.Engine COMMIT
2019-12-10 12:31:21,680 INFO sqlalchemy.engine.base.Engine BEGIN (implicit) 2019-12-10 12:31:21,681 INFO sqlalchemy.engine.base.Engine SELECT appversion.id AS appversion_id, appversion.version AS appversion_version, appversion.`appUrl` AS `appversion_appUrl`, appversion.des AS appversion_des, appversion.`createTime` AS `appversion_createTime`, appversion.`lastModiftyTime` AS `appversion_lastModiftyTime`, appversion.type AS appversion_type FROM appversion WHERE appversion.id = %s 2019-12-10 12:31:21,681 INFO sqlalchemy.engine.base.Engine (1,)

4.ただし、commit後にクエリ結果のオブジェクトを使用すると、エラーが発生する場合があります.Instance is not bound to a Session
この場合、バインドされたセッションが回収され、クエリーができなくなったため、エラーが発生した可能性があります.
 
5、以上のように、安全のために、クエリの結果にdbを加える必要がある.session.expunge(ret)は、クエリー結果とsessionの関係を切断します.ローカルエンティティにすると、キャッシュから消去されず、使用時にクエリーされません.
6、しかしテストの时1つの奇妙な问题を発见して、もう1つのuserのインタフェースを取得して、上のコードとほとんど区别がなくて、意外にも自动rollbackができて、これは私に理解できません.
私のロジックは、クエリー結果(すなわちユーザ)を取得した後、ユーザのステータスフィールドが1であるかどうかを判断し、1であればユーザ属性を変更し、commit、1でなければ操作せず、rollbackも呼び出さない.
しかし、私がテストしたとき、1でなければ自動rollbackになることに気づきました.
これはsqlalchemyの高度な機能かもしれませんか?
 
7、まとめ:
1、sqlalchemyのオブジェクトエンティティ(model)、sessionと連絡を取り合い、get、setなどのmodelをgetしたとき、commitがあってもデータベースと自動的に接続を確立し直す(getのときにselect、setを再確立したときに接続を再確立し、コミットを待つ.コミットしないと、この接続はずっと存在し、最終的には消耗する).自分が何をしているのか、何が起こるのかを確かに理解しない限り、modelのフィールドを慎重に使用します.
2、dbを使用する.session.expungeはエンティティとセッションの関係を切断します.これはいい使い方です.
3、しかし、私はやはり自分でもう1セットのmodelをして、業務層の論理をすることを強くお勧めします.sqlalchemyのオブジェクトエンティティは、データベースの操作にのみ使用されます.これにより、不注意で放出されていない穴を接続することが多くなります.