3

これをライブWebサイトで実行しています。ユーザーがログインすると、私は彼のプロファイルを照会して、利用可能な「クレジット」の数を確認します。クレジットはペイパル経由で購入されます。人がクレジットを購入して支払いが行われた場合、phpmyadmin で同じクエリを実行すると正しい結果が得られますが、クエリはまだ 0 クレジットを示しています。Apache ウェブサーバーを再起動してページをリロードすると、正しい数のクレジットが表示されます。各ユーザーが持っているクレジット数を示すマッパーコードは次のとおりです。

mapper( User, users_table, order_by = 'user.date_added DESC, user.id DESC', properties = {
    'userCreditsCount': column_property( 
        select( 
            [func.ifnull( func.sum( orders_table.c.quantity ), 0 )],
            orders_table.c.user_id == users_table.c.id
        ).where( and_( 
            orders_table.c.date_added > get_order_expire_limit(), # order must not be older than a month
            orders_table.c.status == STATUS_COMPLETED
        ) ).\
        label( 'userCreditsCount' ),
        deferred = True
    )
    # other properties....
} )

フラスコフレームワークでsqlalchemyを使用していますが、フラスコ-sqlalchemyパッケージは使用していません(純粋なsqlalchemyのみ)

データベースを開始する方法は次のとおりです。

engine = create_engine( config.DATABASE_URI, pool_recycle = True )
metadata = MetaData()
db_session = scoped_session( sessionmaker( bind = engine, autoflush = True, autocommit = False ) )

私はこのプロジェクトで python と sqlalchemy の両方を学んだので、何かが欠けているかもしれませんが、これは私を夢中にさせています。何か案は?

4

4 に答える 4

4

セッションで作業する場合、セッションが接続で作業を開始するとすぐに、commit()、rollback()、または close() が呼び出されるまでその接続を保持します。DBAPI を使用すると、トランザクションがコミットまたはロールバックされるまで、データベースへの接続もトランザクション内に残ります。

この場合、データをセッションにロードすると、トランザクションが終了するまで (または、expire() でデータの一部を明示的に期限切れにするまで)、SQLAlchemy はデータを更新しません。これは自然な動作です。トランザクションの分離が原因で、現在のトランザクションは、そのトランザクションが開始されてから発生した変更を認識できない可能性が非常に高いためです。

したがって、expire() または refresh() を使用することは、セッションに最新のデータを取得する方法の一部である場合とそうでない場合がありますが、実際には、トランザクションを終了して新しいトランザクションを開始して、そのトランザクションが開始されてから他の場所で何が変更されたかを真に確認する必要があります。 . 新しいリクエストが入ったときに特定の Session() を準備できるようにアプリケーションを編成する必要がありますが、そのリクエストが完了すると、Session() を閉じて、新しいもの (または少なくとも新しいトランザクション) を作成する必要があります。次のリクエストで起動しました。

于 2012-06-21T06:15:31.697 に答える
2

フィールドにアクセスする前に、オブジェクトに対してrefreshorexpireを呼び出してみてくださいuserCreditsCount:

user1 = session.query(User).get(1)
# ...
session.refresh(user1, ('userCreditsCount',))

これにより、クエリが再度実行されます (更新が呼び出されたとき)。

ただし、トランザクションが使用する分離モードによっては、問題が解決しない場合があります。その場合、クエリで新しい結果を得るために、トランザクション (セッション) をコミット/ロールバックする必要がある場合があります。

于 2012-06-20T14:27:22.077 に答える
1

コンテキスト セッションの有効期間

セッションが終了したら、必ずセッションを閉じてください。

session = db_session()
try:
  return session.query(User).get(5)
finally:
  session.close()
于 2012-06-20T22:58:56.753 に答える
0

ドキュメントによると、 sessionmakerの autocommit を True に設定し、それが役立つかどうかを確認します

ID マップ パターンを使用し、主キーにキー付けされたオブジェクトを格納します。ただし、クエリのキャッシュは一切行いません。

したがって、コードでは次のようになります。

sessionmaker(bind = engine, autoflush = True, autocommit = True)
于 2012-06-15T23:40:16.550 に答える