在我的应用程序中,我使用SQLAlchemy在应用程序重新启动时存储大多数持久数据。为此,我有一个db
包,其中包含我的映射器类(如Tag
,Group
等)和一个使用create_engine
创建单个引擎实例的支持类,使用Session
的全球sessionmaker
工厂。
现在我对如何使用SQLAlchemys会话的理解是,我不会在我的应用程序中传递它们,而是在需要数据库访问时使用全局工厂创建实例。
这导致在一个会话中查询记录然后传递到应用程序的另一部分(使用不同的会话实例)的情况。这给了我这样的例外:
Traceback (most recent call last):
File "…", line 29, in delete
session.delete(self.record)
File "/usr/lib/python3.3/site-packages/sqlalchemy/orm/session.py", line 1444, in delete
self._attach(state, include_before=True)
File "/usr/lib/python3.3/site-packages/sqlalchemy/orm/session.py", line 1748, in _attach
state.session_id, self.hash_key))
sqlalchemy.exc.InvalidRequestError: Object '<Group at 0x7fb64c7b3f90>' is already attached to session '1' (this is '3')
现在我的问题是:我是否使用Session
完全错误(因此我应该一次只使用一个会话并将该会话与数据库中的记录一起传递给其他组件)或者这可能是实际代码问题的结果?
一些示例代码演示了我的确切问题:
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base, declared_attr
Base = declarative_base()
class Record(Base):
__tablename__ = "record"
id = Column(Integer, primary_key=True)
name = Column(String)
def __init__(self, name):
self.name = name
def __repr__(self):
return "<%s('%s')>" % (type(self).__name__, self.name)
engine = create_engine("sqlite:///:memory:")
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
s1 = Session()
record = Record("foobar")
s1.add(record)
s1.commit()
# This would be a completly different part of app
s2 = Session()
record = s2.query(Record).filter(Record.name == "foobar").first()
def delete_record(record):
session = Session()
session.delete(record)
session.commit()
delete_record(record)
答案 0 :(得分:0)
现在我切换到使用单个全局会话实例。在我看来,这既不好看也不干净,但是包括大量的锅炉板代码来从一个会话中删除对象只是为了将它们交给原来的会话后将其交给其他应用程序部分也不是现实的选择。 / p>
如果我开始使用多个线程通过同一个会话访问数据库,我想这会彻底爆发......