How to manage this commit/rollback pattern in sqlalchemy

前端 未结 2 1101
自闭症患者
自闭症患者 2020-12-20 01:29

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


        
2条回答
  •  温柔的废话
    2020-12-20 01:57

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

提交回复
热议问题