How to manage this commit/rollback pattern in sqlalchemy

前端 未结 2 1093
自闭症患者
自闭症患者 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()
    
    0 讨论(0)
  • 2020-12-20 01:59

    You could design a function to manage error handle and you should be evaluating them and consider if you need a performance optimization.

    def commit_or_rollback(my_session, do_something, error_type):
        try:
            do_something(my_session)
            my_session.commit()
            return True
        except error_type as err:
            my_session.rollback()
            print(err)
            return False
    
    def do_something(my_session):
        # do something
    
    commit_result = commit_or_rollback(my_session, do_something, NoResultFound)
    

    Be careful session control and performance. This method could keep the code clearly.

    0 讨论(0)
提交回复
热议问题