我々はピーウィーデータベースが定義されているファイルdb.py
あります)( `アトミック使用せずにピーウィーとの取引を使用して`
db = PostgresqlExtDatabase('mom',
user=DB_CONFIG['username'],
password=DB_CONFIG['password'],
host=DB_CONFIG['host'],
port=DB_CONFIG['port'],
threadlocals=True,
register_hstore=False,
autocommit=True,
autorollback=True,
cursor_factory=DictCursor)
予想通りdb.execute("SOME RAW SQL UPDATE QUERY")
作品を呼び出します。 しかし、その前にbegin
を呼び出しても、DBは変更されません。
db.begin()
db.execute("SOME RAW SQL UPDATE QUERY") # <- Does not wait, db is updated immediately here
db.commit()
私はこれを正しく行いますか?
私は基本的にトランザクションが生存している場合は、トランザクション内に未処理のSQLをネストする必要があります。 トランザクションがない場合はすぐにそれを実行します。begin
が呼び出されます。
これは、私がdb.set_autocommit(False)
を実行した場合、execute_sql
を入力し、次にcommit()
とすると、正常に動作します。
atomic()
コンテキストマネージャ内でも動作します。
いくつかのコンテキストを与えるために、私は、物流上、Webアプリケーションに取り組んで と私たちのコードベースをTrueに設定autocommit
でフラスコSQLAlchemyのscoped_session
を使用しています。 これは(これは..歴史的な理由に)SQLAlchemyのORMを使用してだけでなくSession
オブジェクトとその 、begin()
、begin_nested()
、rollback()
とremove()
方法を使用しません。
それは、ファイルに をセッションSession = scoped_session(sessionmaker(autocommit=True))
を定義して、コードベースでどこでもsession = Session()
を呼び出し、そして時にはsession.execute("SQL")
を使用してクエリを実行することであるない方法、session.begin()
が呼び出されるので、クエリがするまで実行されません。コミット(またはロールバック)。
私たちは今本当にpeeweeを使いたいと思います。 しかし、このセッションでコードベースが構築されています。だから、これは偽装されなければなりません。 すべてのファイルを移動して変更することは不可能であり、起動するテストケースが十分ではありません(歴史的な理由から)。
はまた、私はいくつかの質問があったが、私は彼らに聞いてどこかわからないので、私は、私はここにそれらを置く場合は、気にしないことを望む:
は、このDBオブジェクトです(とその接続)は、実行中のスレッドにバインドされていますか? dbが2つの異なるファイルからインポートされ、それぞれから
db.begin()
が呼び出されると、基本的にいくつかのバグがありますか? 上記のdb
オブジェクトのid
がスレッドごとに同じであることをipythonシェルで確認することができます。 psycopg2接続が再作成されない限り、これは分離する必要があると仮定して正しいですか? SQLAlchemyのSession
を偽装する、私は必要なセッションの種類を返すラッパークラス、 SQLA
Session
オブジェクト、または私はそれを偽装するためにピーウィーのために書かれてきたラッパーを作成しました。class SessionMocker(object): # DO NOT make this a singleton. Sessions will break def __init__(self, orm_type=ORM_TYPES.SQLA): assert orm_type in ORM_TYPES, "Invalid session constructor type" super(SessionMocker, self).__init__() self.orm_type = orm_type def __call__(self, *args, **kwargs): if self.orm_type == ORM_TYPES.SQLA: return SQLASession(*args, **kwargs) if self.orm_type == ORM_TYPES.PEEWEE: # For now lets assume no slave return SessionWrapper(*args, **kwargs) raise NotImplementedError def __getattr__(self, item): """ Assuming this will never be called without calling Session() first. Else there is no way to tell what type of Session class (ORM) is required, since that can't be passed. """ if self.orm_type == ORM_TYPES.SQLA: kls = SQLASession elif self.orm_type == ORM_TYPES.PEEWEE: kls = SessionWrapper else: raise NotImplementedError return getattr(kls, item) Session = SessionMocker(ORM_TYPES.SQLA)
私は、これはコードベースはどこにでもそれを変更することなく、ピーウィーを使用する上で、透明かつシームレスな切り替えを行うことができます考え出しました。 これをよりうまくいくにはどうすればいいですか?
私は、実際に私は内部で 'atomic'を呼び出す' SessionWrapper'オブジェクトの内部で、あなたの '_atomic'、' transaction'と 'savepoint'コンテキストマネージャをラップしようとしたことを試してみました、しかし、私はsqlalchemyのスコープセッションだけでコミットとロールバック以上のものだと思います。結局、ピューニーのための計画を落とさなければなりませんでしたが、将来私たちのマイクロサービスでそれを使用できることを願っています。それはまさに私たちが必要としているようです。 ラッパーを調べる場合は、私はあなたにそれを送ることができますか? – kunl
それはあなたには役に立たない場合、私はそれを見てどのような利益があるか分からない。 SQLAlchemyの幸運、tho – coleifer
とにかく、ありがとう、すばらしい図書館のおかげでありがとう。私は軽量プロジェクト用のより簡単なORMがほしいと思っていました。また、フィルタ( 'some__join')のようなdjangoのサポートを完全に落としていますか? – kunl