为什么需要重做自动映射? (SQL炼金术)
Why redoing automapping is necessary? (SQLAlchemy)
我正在尝试理解代码,它大致执行以下操作:
# db.py module
engine = create_engine(DB_URL, pool_timeout=20, pool_recycle=1)
def get_session():
return scoped_session(sessionmaker(bind=engine, expire_on_commit=False))()
def get_base():
base = automap_base()
base.prepare(engine, reflect=True)
return base
base = get_base()
User = base.classes.user
在某些函数中:
# other.py module
from db import get_base, get_session, User
def some_func():
sess = get_session()
# do something with sess and User:
user = sess.query(User).first()
User2 = get_base().classes.user
try:
check = sess.query(User2).first()
except:
sess.rollback()
# do more with sess
sess.commit()
可以在 celery 任务中调用 some_func
,但没有使用 greenlets 或其他类似的 monkey-patch 并发技巧。
我想知道,通过重新映射元数据可以实现什么?我的理解是否正确,那么由于作用域会话 SQLAlchemy 无论如何都会有相同的对象?在这种情况下,甚至会话似乎都是一样的。
重点是什么?
虽然我关于获得相同对象的假设是错误的:
(Pdb) pp user
<sqlalchemy.ext.automap.user object at 0x7f62e1a57390>
(Pdb) pp check
<sqlalchemy.ext.automap.user object at 0x7f62e0e93750>
(Pdb) pp user == check
False
(Pdb) pp user.id
1L
(Pdb) pp check.id
1L
(id
是主键,即唯一)
看来 SQLAlchemy 会分别保存来自不同基础的对象。
到目前为止我最好的猜测是这个技巧允许在当前 运行 交易之外进行例如用户存在测试。
大多数时候没有必要,只会减慢应用程序的速度。当应用程序 运行 时,数据库架构通常不会经常更改,简单的更改应该无关紧要(请参阅 "Data independence")。重做反射等似乎只是人们在做的事情——可能是因为害怕使用全局变量。另一方面,在您的示例中,首先似乎在 db.py
中反射仅完成一次以生成全局 base
和 User
类.
这同样适用于范围会话注册表。注册表本身旨在为线程本地会话提供服务,因此一直重新创建它没有意义。相反,它应该是一个应用程序范围的单例。应该注意的是,使用作用域会话意味着您的应用程序以与其兼容的方式使用线程,或者换句话说,单个线程应该处理单个作业,例如 request/response 等,以便生命周期会话的生命周期自然绑定到线程的生命周期。
由于基础和模型的重建,您关于获得相同对象的假设被打破 类。尽管它们代表数据库中的同一行,但它们是不同的模型,因此会在会话中产生不同的对象。
我正在尝试理解代码,它大致执行以下操作:
# db.py module
engine = create_engine(DB_URL, pool_timeout=20, pool_recycle=1)
def get_session():
return scoped_session(sessionmaker(bind=engine, expire_on_commit=False))()
def get_base():
base = automap_base()
base.prepare(engine, reflect=True)
return base
base = get_base()
User = base.classes.user
在某些函数中:
# other.py module
from db import get_base, get_session, User
def some_func():
sess = get_session()
# do something with sess and User:
user = sess.query(User).first()
User2 = get_base().classes.user
try:
check = sess.query(User2).first()
except:
sess.rollback()
# do more with sess
sess.commit()
可以在 celery 任务中调用 some_func
,但没有使用 greenlets 或其他类似的 monkey-patch 并发技巧。
我想知道,通过重新映射元数据可以实现什么?我的理解是否正确,那么由于作用域会话 SQLAlchemy 无论如何都会有相同的对象?在这种情况下,甚至会话似乎都是一样的。
重点是什么?
虽然我关于获得相同对象的假设是错误的:
(Pdb) pp user
<sqlalchemy.ext.automap.user object at 0x7f62e1a57390>
(Pdb) pp check
<sqlalchemy.ext.automap.user object at 0x7f62e0e93750>
(Pdb) pp user == check
False
(Pdb) pp user.id
1L
(Pdb) pp check.id
1L
(id
是主键,即唯一)
看来 SQLAlchemy 会分别保存来自不同基础的对象。
到目前为止我最好的猜测是这个技巧允许在当前 运行 交易之外进行例如用户存在测试。
大多数时候没有必要,只会减慢应用程序的速度。当应用程序 运行 时,数据库架构通常不会经常更改,简单的更改应该无关紧要(请参阅 "Data independence")。重做反射等似乎只是人们在做的事情——可能是因为害怕使用全局变量。另一方面,在您的示例中,首先似乎在 db.py
中反射仅完成一次以生成全局 base
和 User
类.
这同样适用于范围会话注册表。注册表本身旨在为线程本地会话提供服务,因此一直重新创建它没有意义。相反,它应该是一个应用程序范围的单例。应该注意的是,使用作用域会话意味着您的应用程序以与其兼容的方式使用线程,或者换句话说,单个线程应该处理单个作业,例如 request/response 等,以便生命周期会话的生命周期自然绑定到线程的生命周期。
由于基础和模型的重建,您关于获得相同对象的假设被打破 类。尽管它们代表数据库中的同一行,但它们是不同的模型,因此会在会话中产生不同的对象。