2012-04-08 36 views
9

Tôi đang sử dụng sql thuật giả kim trong dự án của tôi, tôi đã sử dụng phiên db,Giao dịch sử dụng trong thuật toán giả kim thuật trong khi sử dụng phiên db như thế nào?

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 phiên sử dụng như:

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

Bây giờ tôi muốn chèn dữ liệu vào hai bảng đặt hàng và mục hàng trật tự Vì vậy, tôi cần giao dịch, là: 1. Trong lần chèn đầu tiên, tôi muốn id của đơn đặt hàng được chèn vào sử dụng trong truy vấn chèn thứ hai 2. Nếu truy vấn chèn thứ hai không thành công thì truy vấn đầu tiên sẽ được khôi phục

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() 

Cách sử dụng tính năng quản lý?

Trả lời

15

Giao dịch lồng nhau, theo đề xuất của Lafada, không dành cho tình huống như vậy. A flush() sẽ hoạt động tốt, ví dụ:

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() 

Hoặc tốt hơn nếu bạn thiết lập mối quan hệ đúng thứ tự và mục hàng, bạn thậm chí không nên chỉ định id theo cách thủ công.

+3

Tôi sẽ sử dụng 'với db_session.begin(): ...' và nếu có thể, hãy xóa 'try: ... except: ...' vì nó đang ẩn tất cả các ngoại lệ. – Governa

+0

'flush' cũng không được dự định. Xem câu trả lời của tôi làm thế nào nó nên được thực hiện! – schlamar

1

Bạn phải sử dụng nested transaction như

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() 

Bạn cũng có thể sử dụng two phase giao dịch. Cả hai đều có lợi thế của nó mà một trong những phù hợp cho bạn mà bạn có thể sử dụng

5

Bạn nên sử dụng tính năng relationship của SQLAlchemy, vì vậy bạn không phải gây rối với các khóa ngoại. Vì vậy, ví dụ mục đặt hàng của bạn có thể trông giống như (tôi giả sử bạn có một nhiều một mối quan hệ):

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

Và trên chèn bạn sẽ chỉ giao cho ví dụ theo thứ tự:

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

Xem thêm chi tiết trong hướng dẫn: http://docs.sqlalchemy.org/en/latest/orm/relationships.html

Các vấn đề liên quan