在使用 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() 甚至什么时候删除 session ,我一直遇到麻烦,尤其是在查询时,某些 session 不会关闭并且数据库会挂起。什么是更好的模式? (请注意,我想将所有方法都包装在模型本身中,而不是在其他一些全局命名空间中)
最佳答案
简短回答:它是特定于应用程序的。
如果您正在实现长时间运行的进程(如后端守护进程),您可能需要在每个 session 生命周期内执行多次提交。如果您正在开发 HTTP 应用程序,则模式通常是每个 HTTP 请求一次提交(在最后,在连接断开时)。大多数现代 Web 框架都提供请求设置/拆卸的 Hook 。例如,在 Flask 中,您可以将 session.commit()/session.close() 放在用 @app.teardown_request 装饰的方法下。
我推荐以下方法:
- (来自 SQLAlchemy 文档)作为一般规则,将 session 的生命周期与访问和/或操作数据库数据的函数和对象分开并置于外部。这将极大地有助于实现可预测且一致的交易范围。
- 用 session.flush() 语句替换上面的 session.commit() 语句。 flush() 将在不提交事务的情况下保留数据。删除 session.close() 语句。请记住,session.close() 会将连接返回给引擎/连接池,它实际上并没有关闭连接。
- 实现您的自定义 DBRollbackException() 异常,使用它在出现任何错误时回滚当前事务。
- 在最后提交一次(例如,根据要求拆卸)
关于python - SQLAlchemy:将当前 session 包装到模型中的正确方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34560607/