เท่าที่ฉันทราบไม่มีวิธีใดที่จะทำให้ ORM ออกเม็ดมีดจำนวนมากได้ ฉันเชื่อว่าเหตุผลพื้นฐานคือ SQLAlchemy จำเป็นต้องติดตามข้อมูลประจำตัวของแต่ละออบเจ็กต์ (เช่นคีย์หลักใหม่) และส่วนแทรกจำนวนมากเข้าไปยุ่งเกี่ยวกับสิ่งนั้น ตัวอย่างเช่นสมมติว่าfoo
ตารางของคุณมีid
คอลัมน์และแมปกับFoo
คลาส:
x = Foo(bar=1)
print x.id
# None
session.add(x)
session.flush()
# BEGIN
# INSERT INTO foo (bar) VALUES(1)
# COMMIT
print x.id
# 1
เนื่องจาก SQLAlchemy รับค่าx.id
โดยไม่ต้องออกแบบสอบถามอื่นเราจึงสามารถสรุปได้ว่าได้รับค่าโดยตรงจากINSERT
คำสั่ง หากคุณไม่ต้องการการเข้าถึงวัตถุที่สร้างขึ้นในภายหลังผ่านอินสแตนซ์เดียวกันคุณสามารถข้ามเลเยอร์ ORM สำหรับส่วนแทรกของคุณได้:
Foo.__table__.insert().execute([{'bar': 1}, {'bar': 2}, {'bar': 3}])
# INSERT INTO foo (bar) VALUES ((1,), (2,), (3,))
SQLAlchemy ไม่สามารถจับคู่แถวใหม่เหล่านี้กับออบเจ็กต์ใด ๆ ที่มีอยู่ได้ดังนั้นคุณจะต้องสอบถามใหม่สำหรับการดำเนินการในภายหลัง
เท่าที่เกี่ยวข้องกับข้อมูลเก่าคุณควรจำไว้ว่าเซสชันไม่มีวิธีในตัวที่จะทราบได้ว่าเมื่อใดที่ฐานข้อมูลมีการเปลี่ยนแปลงนอกเซสชัน เพื่อที่จะปรับเปลี่ยนการเข้าถึงข้อมูลจากภายนอกผ่านทางอินสแตนซ์ที่มีอยู่กรณีจะต้องมีการทำเครื่องหมายว่าหมดอายุ นี้เกิดขึ้นโดยเริ่มต้นในsession.commit()
แต่สามารถทำได้ด้วยตนเองโดยการเรียกหรือsession.expire_all()
session.expire(instance)
ตัวอย่าง (ละเว้น SQL):
x = Foo(bar=1)
session.add(x)
session.commit()
print x.bar
# 1
foo.update().execute(bar=42)
print x.bar
# 1
session.expire(x)
print x.bar
# 42
session.commit()
หมดอายุx
ดังนั้นคำสั่งการพิมพ์ครั้งแรกจะเปิดธุรกรรมใหม่โดยปริยายและx
แอตทริบิวต์ของการสืบค้นใหม่ หากคุณแสดงความคิดเห็นในใบแจ้งยอดการพิมพ์ครั้งแรกคุณจะสังเกตเห็นว่าคำสั่งที่สองรับค่าที่ถูกต้องแล้วเนื่องจากแบบสอบถามใหม่จะไม่ถูกปล่อยออกมาจนกว่าจะมีการอัปเดต
สิ่งนี้สมเหตุสมผลจากมุมมองของการแยกธุรกรรม - คุณควรเลือกเฉพาะการแก้ไขภายนอกระหว่างธุรกรรมเท่านั้น session.expire_all()
ถ้านี่เป็นสาเหตุที่ทำให้คุณเดือดร้อนผมขอแนะนำให้ชัดเจนอีกครั้งหรือคิดโปรแกรมประยุกต์ของคุณขอบเขตการทำธุรกรรมแทนทันทีถึงการ