SQLAlchemy: 提交后对象映射丢失?
我在使用SQLAlchemy时遇到了一个简单的问题。我有一个表格里的模型,我们称它为Model1。我想在这个表格中添加一行数据,并获取自动增加的键值,这样我就可以用这个键值创建另一个模型,并在其中使用它。这样做并不是因为数据库设计有问题(比如一对一关系等)。我只是需要这个键值在另一个表中,因为那个表要传输到远程主机,我需要匹配的键值,以便服务器之间能够相互理解。这两个表之间不会有进一步的本地引用,也无法建立关系。
考虑以下代码:
object1 = model.Model1(param)
DBSession.add(object1)
# if I do this, the line below fails with an UnboundExecutionError.
# and if I dont do this, object1.id won't be set yet
#transaction.commit()
object2 = model.AnotherModel(object1.id) #id holds the primary, autoincremented key
我希望我甚至不需要“手动”提交。基本上,我想实现的是,“Model1”会不断增长,主键Model.id会逐渐增加。而另一个模型(AnotherModel)总是只是Model1的一小部分,这部分还没有被处理。当然,我可以在“Model1”中添加一个标志,也就是在表中加一个布尔字段来标记已经处理过的元素,但我希望这样做不是必要的。
我该如何让上面的代码正常工作呢?
问候,
汤姆
3 个回答
我之前只在使用外键的时候遇到过这个问题,所以在第二种情况下,你应该这样写:model.AnotherModel(model1=object1),然后就能正常工作了。所以我觉得可能是你的模型出了问题,也许你可以把它们发出来看看?
如果你想在没有提交任何内容的情况下获取新的主键标识符,只需调用 session.flush()。这样会把当前事务中所有待处理的内容发送到数据库。
有几点需要说明:
- 能不能解释一下变量
transaction
是指什么? - 到底是哪个语句引发了 UnboundExecutionError 错误?
- 请提供完整的异常信息,包括堆栈跟踪。
- 在这种情况下,通常的做法是调用
DBSession.flush()
。你试过这个吗?
举个例子:
object1 = Model1(param)
DBSession.add(object1)
DBSession.flush()
assert object1.id != None # flushing the session populates the id
object2 = AnotherModel(object1.id)
如果想要更好地理解 SA 会话以及 flush()
的作用,可以查看 使用会话。
简单来说,flush()
会把待处理的实例变成持久的,也就是说新的对象会被插入到数据库表中。flush()
还会更新那些会话中跟踪的有变化的实例的值。
commit()
在执行时总是会先调用 flush()
。
在一个事务中,你可以多次调用 flush。每次 flush() 都会在数据库中进行更新和/或插入。整个事务可以选择提交或回滚。