2012-04-08 45 views
9

我使用SQL鍊金術在我的項目,我用DB會話,在使用db會話時如何在sql鍊金術中使用事務?

engine = create_engine(configuration) 
db_session = scoped_session(sessionmaker(autocommit=False, 
            autoflush=False, 
            bind=engine)) 

Base = declarative_base() 
Base.query = db_session.query_property() 

def init_db():  
    import models 
    Base.metadata.create_all(bind=engine) 

DB會話使用:

db_session.merge(order)  #order(model) in object 
db_session.commit() 

現在我想在兩個表訂單和訂單行項目中插入數據,所以我需要交易, 爲: 1.在第一次插入我要插入的訂單的ID在第二插入查詢使用 2.如果第二插入查詢失敗則第一個查詢應回滾

Try: 
    #begin transaction/How to begin transaction? 
    order=db_session.add(order)  #insert into order 
    #is need to commit db_session here as I need inserted orders id 
    #here actually db_session.commit() needed to get order's id(auto generated) 
    #if db_session committed here then sql alchemy starts new session  

    order_line_item.id = order.id 
    db_session.add(order_line_item) #insert into order line line item 

    db_session.commit() 
    #check transaction status if failed then rollback, How to check status? 

except: 
    db_session.rollback() 

如何使用trasaction?

回答

15

Lafada建議的嵌套事務不適用於這種情況。 A flush()可以做得很好,例如

db_session.begin() 
try: 
    db_session.add(order) 

    db_session.flush() 

    order_line_item.id = order.id 
    db_session.add(order_line_item) 

    db_session.commit() 
except: 
    db_session.rollback() 

或者更好的是,如果你有關係,正確安裝訂單與項目之間,你應該甚至懶得手動分配的ID。

+3

我將使用'with db_session.begin():...',並且如果可能,刪除'try:... except:...',因爲它隱藏了所有異常。 – Governa 2012-07-27 16:21:49

+0

'flush'也不適用。看到我的答案應該怎麼做! – schlamar 2013-01-14 14:50:14

1

你有用戶nested transaction

top_trans = connection.begin() 
try: 
    #begin transaction/How to begin transaction? 
    order_trans = connection.begin() 
    order=db_session.add(order)  #insert into order 
    order_trans.commit() 

    order_line_item.id = order.id 
    order_line_trans = connection.begin() 
    db_session.add(order_line_item) #insert into order line line item 

    order_line_trans.commit() 
    #check transaction status if failed then rollback, How to check status? 

except: 
    top_trans.rollback() 

您還可以使用two phase交易。兩者都有其優勢,哪一個適合您,您可以使用

5

你應該使用SQLAlchemy的relationship功能,所以你不要用 來弄亂外鍵。因此,例如,您的訂單項可以 樣子(我假設你有一個多合一的關係):

class OrderLineItem(Base): 
    id = Column(Integer, primary_key=True) 
    order_id = Column(Integer, ForeignKey('orders.id')) 
    order = relationship('Order', backref='order_line_items') 

而且在插入時你只需指定單實例:

order_line_item.order = order 
session.add(order) # you even don't have to insert the item! 

查看更多詳細信息在本教程中:http://docs.sqlalchemy.org/en/latest/orm/relationships.html