sessionmaker()
là một nhà máy, nó ở đó để khuyến khích đặt các tùy chọn cấu hình để tạo các Session
đối tượng mới chỉ ở một nơi. Nó là tùy chọn, ở chỗ bạn có thể dễ dàng gọi Session(bind=engine, expire_on_commit=False)
bất cứ lúc nào bạn cần một cái mới Session
, ngoại trừ sự dài dòng và dư thừa của nó, và tôi muốn ngăn chặn sự gia tăng của những "người trợ giúp" quy mô nhỏ mà mỗi người đều tiếp cận vấn đề dư thừa này trong một số và cách khó hiểu hơn.
Vì vậy, sessionmaker()
chỉ là một công cụ giúp bạn tạo ra Session
các đối tượng khi bạn cần.
Phần tiếp theo. Tôi nghĩ câu hỏi đặt ra là, sự khác biệt giữa việc tạo ra một cái mới Session()
ở nhiều điểm khác nhau so với việc chỉ sử dụng một cái suốt đời. Câu trả lời, không nhiều lắm. Session
là một vùng chứa cho tất cả các đối tượng mà bạn đặt vào đó và sau đó nó cũng theo dõi một giao dịch đang mở. Tại thời điểm bạn gọi rollback()
hoặc commit()
, giao dịch đã kết thúc và Session
không có kết nối với cơ sở dữ liệu cho đến khi nó được gọi để phát ra SQL một lần nữa. Các liên kết mà nó nắm giữ với các đối tượng được ánh xạ của bạn là tham chiếu yếu, miễn là các đối tượng sạch sẽ với các thay đổi đang chờ xử lý, vì vậy ngay cả về mặt đó, nó Session
sẽ tự trống trở lại trạng thái hoàn toàn mới khi ứng dụng của bạn mất tất cả các tham chiếu đến các đối tượng được ánh xạ. Nếu bạn để mặc định"expire_on_commit"
thiết lập, sau đó tất cả các đối tượng sẽ hết hạn sau một cam kết. Nếu điều đó Session
bị treo trong năm hoặc hai mươi phút và tất cả các loại thứ đã thay đổi trong cơ sở dữ liệu vào lần tiếp theo bạn sử dụng nó, nó sẽ tải tất cả trạng thái hoàn toàn mới vào lần tiếp theo bạn truy cập các đối tượng đó mặc dù chúng đã được lưu trong bộ nhớ. trong hai mươi phút.
Trong các ứng dụng web, chúng ta thường nói, tại sao bạn không tạo một thương hiệu mới Session
cho mỗi yêu cầu, thay vì sử dụng lặp đi lặp lại cùng một thương hiệu . Thực hành này đảm bảo rằng yêu cầu mới bắt đầu "sạch". Nếu một số đối tượng từ yêu cầu trước đó vẫn chưa được thu dọn và nếu có thể bạn đã tắt "expire_on_commit"
, có thể một số trạng thái từ yêu cầu trước vẫn còn tồn tại và trạng thái đó thậm chí có thể đã khá cũ. Nếu bạn cẩn thận expire_on_commit
bật và chắc chắn kết thúc cuộc gọi commit()
hoặc rollback()
theo yêu cầu thì không sao cả, nhưng nếu bạn bắt đầu với một thương hiệu mới Session
, thì thậm chí không có bất kỳ câu hỏi nào cho thấy bạn đang bắt đầu sạch sẽ. Vì vậy, ý tưởng bắt đầu mỗi yêu cầu bằng mộtSession
thực sự chỉ là cách đơn giản nhất để đảm bảo rằng bạn đang bắt đầu mới và làm cho việc sử dụng expire_on_commit
khá nhiều tùy chọn, vì cờ này có thể phát sinh thêm rất nhiều SQL cho một hoạt động gọi commit()
ở giữa một chuỗi hoạt động. Không chắc chắn nếu điều này trả lời câu hỏi của bạn.
Vòng tiếp theo là những gì bạn đề cập về luồng. Nếu ứng dụng của bạn là đa luồng, chúng tôi khuyên bạn nên đảm bảo rằng ứng Session
dụng đang sử dụng là cục bộ cho ... thứ gì đó. scoped_session()
theo mặc định làm cho nó cục bộ thành luồng hiện tại. Trong một ứng dụng web, cục bộ cho yêu cầu trên thực tế thậm chí còn tốt hơn. Flask-SQLAlchemy thực sự gửi một "chức năng phạm vi" tùy chỉnh để scoped_session()
bạn nhận được một phiên theo phạm vi yêu cầu. Ứng dụng Kim tự tháp trung bình gắn Phiên vào sổ đăng ký "yêu cầu". Khi sử dụng các lược đồ như thế này, ý tưởng "tạo Phiên mới khi bắt đầu theo yêu cầu" tiếp tục giống như cách đơn giản nhất để giữ mọi thứ suôn sẻ.