如何在使用db session时在sql alchemy中使用事务?

时间:2012-04-08 13:55:03

标签: transactions sqlalchemy

我在我的项目中使用sql alchemy,我使用了db session,

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_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?

3 个答案:

答案 0 :(得分:17)

Lafada建议的嵌套交易不适用于此类情况。 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。

答案 1 :(得分: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

答案 2 :(得分: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交易。两者都有一个优势,哪一个适合你,你可以使用