在我的应用程序中,我使用 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)