Using SAVEPOINT
SAVEPOINT transactions, if supported by the underlying engine, may bedelineated using the begin_nested()
method:
Session = sessionmaker()
session = Session()
session.add(u1)
session.add(u2)
session.begin_nested() # establish a savepoint
session.add(u3)
session.rollback() # rolls back u3, keeps u1 and u2
session.commit() # commits u1 and u2
begin_nested()
may be called any numberof times, which will issue a new SAVEPOINT with a unique identifier for eachcall. For each begin_nested()
call, acorresponding rollback()
orcommit()
must be issued. (But note that if the return value isused as a context manager, i.e. in a with-statement, then this rollback/commitis issued by the context manager upon exiting the context, and so should not beadded explicitly.)
When begin_nested()
is called, aflush()
is unconditionally issued(regardless of the autoflush
setting). This is so that when arollback()
occurs, the full state of thesession is expired, thus causing all subsequent attribute/instance access toreference the full state of the Session
rightbefore begin_nested()
was called.
begin_nested()
, in the same manner as the less oftenused begin()
method, returns a SessionTransaction
objectwhich works as a context manager.It can be succinctly used around individual record inserts in order to catchthings like unique constraint exceptions:
for record in records:
try:
with session.begin_nested():
session.merge(record)
except:
print("Skipped record %s" % record)
session.commit()