Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.4k views
in Technique[技术] by (71.8m points)

python - How to manage this commit/rollback pattern in sqlalchemy

I find myself repeating a lot of this in sqlalchemy, I wonder what's the best way to handle it?

try:
    #do some database query
    db_session.commit()
except: #some exception handling
    db_session.rollback()
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

This is right from my working code, a method of a session registry wrapper.

It is used this way:

# dblink is an object that knows how to connect to the database
with dblink.CommittingSession() as session:
  session.add(...)
  # do anything else.
# at this point, session.commit() has been called.

Or:

try:
  with dblink.CommittingSession() as session:
    session.add(...)
except ...:
  # at this point, session.rollback has been called.
  log.error('We failed!')

The implementation:

from contextlib import contextmanager

class DbLink(object):
    """This class knows how to connect to the database."""
    # ...
    # Basically we wrap a sqlalchemy.orm.sessionmaker value here, in session_registry.
    # You might want to create sessions differently.  

    @contextmanager
    def CommittingSession(self, **kwargs):
      """Creates a session, commits at the end, rolls back on exception, removes.

      Args:
        **kwargs: optional; supplied to session_registry while asking
          to construct a session (mostly for testing).

      Yields:
        a session object. The session will .commit() when a `with CommittingSession()`
        statement terminates normally, or .rollback() on an exception.
      """
      try:
        session = self.session_registry(**kwargs)  # this gives us a session.
        # transaction has already begun here, so no explicit .begin().
        yield session
      except:
        session.rollback()
        raise
      else:
        session.commit()
      finally:
        # Note: close() unbinds model objects, but keeps the DB connection.
        session.close()
        self.session_registry.remove()

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

56.6k users

...