2011-09-16 10 views
3

SQLalchemyに問題が発生しました。ここに私のシナリオがあります。テーブルに追加するレコードのリストがあります。レコードがテーブルに追加されたら、挿入されたレコードIDを取得し、別のテーブルに別のレコードを挿入する必要があります。私はこれらの操作をシングルセッションで行っています。私は、コードにループ内でSQLAlchemyセッションオブジェクトを使用してデータをコミットするときに問題が発生しました。

を与えることを許可されておりませんように、コードの構造を以下に示すレコードが挿入されるリストセッションオブジェクト

ループ作成:ここ

do the session.add(obj) 

session.commit() 

get obj.id 

do the session.add(obj2) # with obj2 having the id from the obj 

session.commit() 

にデータを取得している唯一の最後のレコードを複数のレコードを持っていると正しくコミットされます

この問題を解決するのに手伝ってください。

+0

同じ問題があるいくつかのサンプルコードを記述することは不可能です – knitti

答えて

4

あなたはこれを使用するようにコードを再構築してみてください可能性があります、

一つの場所でコミット/ロールバック・ロジックを処理
def updatetxn(pk, newvalue): 
    def txn(session): 
    obj = session.query(myclass).filter_by(id=pk).one() 
    obj.field = newvalue 
    session.add(obj) 
    return txn 

transaction(updatetxn(4, 'abc')) 

Session = sqlalchemy.orm.sessionmaker(...) 
def transaction(self, callback): 
    session = sqlalchemy.orm.scoped_session(Session) 
    try: 
    result = callback(session) 
    except: 
    session.rollback() 
    raise 
    else: 
    session.commit() 
    finally: 
    session.close() 
    return result 

次に、各トランザクションはそうのように、独自の機能に行きます関数スコープを使用して作業単位をスコープすることは、アプリケーションの複雑さを軽減し、まだ見つけていないバグを排除することができます。

7

はありませんは2つのコミットを発行する必要があります。 sqlalchemyセッションを使用する主な理由の1つは、オブジェクトがどのように相互に関連するかを理解し、データが正しく挿入され、目的の構造を正しく表すように挿入を順序付けます。これは、主にrelationship構造を使用して動作します。ここでは簡単な例を示します。

>>> from sqlalchemy import * 
>>> from sqlalchemy.orm import * 
>>> from sqlalchemy.ext.declarative import declarative_base 
>>> Base = declarative_base() 

>>> class A(Base): 
...  __tablename__ = "a_table" 
...  id = Column(Integer, primary_key=True) 
... 
>>> class B(Base): 
...  __tablename__ = "b_table" 
...  id = Column(Integer, primary_key=True) 
...  a_id = Column(Integer, ForeignKey(A.id)) 
...  a = relationship(A) 
... 
>>> my_a = A() 
>>> my_b = B() 
>>> my_b.a = my_a 
>>> 

最も重要な部分は、我々はB.aを通じてABとの関係を宣言しているということです。これを最大限に活用するには、この関係プロパティを使用してそれぞれのインスタンス間の関係を表現し、sqlalchemyがa_id列自体を設定するようにしておくことが重要です。 echo=True

>>> engine = create_engine("sqlite:///:memory:") 
>>> Base.metadata.create_all(engine) 
>>> engine.echo = True 
>>> Session = sessionmaker(engine) 
>>> 
>>> session = Session() 
>>> session.add(my_a) 
>>> session.add(my_b) 
>>> 
>>> session.commit() 

、出力はビット次のようになります。my_aオブジェクトが挿入されていることを

2011-09-16 17:19:22,367 INFO sqlalchemy.engine.base.Engine.0x...ed50 BEGIN (implicit) 
2011-09-16 17:19:22,368 INFO sqlalchemy.engine.base.Engine.0x...ed50 INSERT INTO a_table DEFAULT VALUES 
2011-09-16 17:19:22,368 INFO sqlalchemy.engine.base.Engine.0x...ed50() 
2011-09-16 17:19:22,369 INFO sqlalchemy.engine.base.Engine.0x...ed50 INSERT INTO b_table (a_id) VALUES (?) 
2011-09-16 17:19:22,369 INFO sqlalchemy.engine.base.Engine.0x...ed50 (1,) 
2011-09-16 17:19:22,369 INFO sqlalchemy.engine.base.Engine.0x...ed50 COMMIT 

お知らせ、およびSQLAlchemyのは、割り当てられた主キーを読み取り、my_bのための挿入のためにそれを使用しています。

関連する問題