SQLAlchemy:将当前会话包装到模型中的正确方法?

时间:2016-01-01 22:18:48

标签: python sqlalchemy

在使用SQLalchemy构建模型时,我正在使用declarative_base ... 所以我有一个看起来像这样的模型:

from sqlalchemy.orm import sessionmaker, scoped_session                             
engine = create_engine("mysql...")
session_factory = sessionmaker(bind=engine)                                         
SessionHeap = scoped_session(session_factory)          
Base = declarative_base()

class MyTable(Base, Actions):                                                      
    __tablename__ = 'mytable'                                                     
    id = Column(Integer, primary_key=True)                                       
    date = Column(Integer)                                                                                                      
    tag = Column(String(50))

class Actions(object):                                                              
    @classmethod                                                                    
    def create(cls, **kwargs):                                                      
        session = SessionHeap()                                                     
        session.add(cls(**kwargs))                                                  
        session.commit()                                                            
        session.close()                                                             
        SessionHeap.remove()                                                        

    def update(self, **kwargs):                                                     
        for key, val in kwargs.iteritems():                                         
            self.__setattr__(key, val)                                              
        session = inspect(self).session                                             
        session.commit()                                                            

    @classmethod                                                                    
    def _search(cls, **kwargs):                                                     
        session = SessionHeap()                                                     
        query = session.query(cls).filter_by(**kwargs)                              
        session.commit()                                                            
        session.close()                                                             
        SessionHeap.remove()                                                        
        return query         

我不确定何时应该调用session.close(),甚至何时删除会话,我一直遇到麻烦,特别是对于查询,某些会话不会关闭而数据库挂起。什么是更好的模式呢? (注意我想保留所有方法包含在模型本身中,而不是在其他一些全局命名空间中)

1 个答案:

答案 0 :(得分:2)

简短回答:这是针对特定应用的。

如果您正在实施长时间运行的进程(如后端守护进程),则可能需要在每个会话生命周期内执行多次提交。如果您正在使用HTTP应用程序,则该模式通常是每个HTTP请求一次提交(最后,在连接拆除时)。大多数现代Web框架都提供了请求设置/拆卸的钩子。例如,在Flask中,您可以将session.commit()/ session.close()放在用@ app.teardown_request修饰的方法下。

我建议采用以下方法:

  • (来自SQLAlchemy docs)作为一般规则,将会话的生命周期与访问和/或操作数据库数据的函数和对象分开并保持外部。这将极大地帮助实现可预测且一致的事务范围。
  • 使用session.flush()语句替换上面的session.commit()语句。 flush()将保留数据而不提交事务。删除session.close()语句。请记住,session.close()会将连接返回给Engine /连接池,它实际上并不关闭连接。
  • 实现自定义DBRollbackException()异常,使用它在任何错误上回滚当前事务。
  • 在最后提交一次(例如,请求拆解)