如何用一个SQLAlchemy模型保存到两个表中

1 投票
2 回答
2335 浏览
提问于 2025-04-15 22:53

我有一个使用SQLAlchemy的ORM类,它连接到MySQL数据库,能很好地把我需要的数据保存到基础表中。不过,我还想把相同的数据也保存到一个第二个归档表里。

下面是一些伪代码,试着解释一下我的意思:

my_data = Data() #An ORM Class
my_data.name = "foo"

#This saves just to the 'data' table
session.add(my_data)

#This will save it to the identical 'backup_data' table
my_data_archive = my_data
my_data_archive.__tablename__ = 'backup_data'
session.add(my_data_archive)

#And commits them both
session.commit()

顺便说一下,我对将一个类映射到JOIN不感兴趣,具体来说就是:http://www.sqlalchemy.org/docs/05/mappers.html#mapping-a-class-against-multiple-tables

2 个回答

1

创建两个一模一样的模型:一个对应主表,另一个对应归档表。然后创建一个叫做 MapperExtension 的东西,并重新定义一个方法 after_insert()(根据你的需求,你可能还需要 after_update()after_delete())。这个方法的作用是把主模型中的数据复制到归档中,并把它添加到会话里。有一些小技巧可以自动复制所有的列和多对多关系。

需要注意的是,你必须调用 flush() 两次来存储这两个对象,因为在映射器扩展把新对象添加到会话之前,工作单元的计算已经完成了。你可以重新定义 Session.flush() 来解决这个问题。另外,自增字段是在对象被刷新时分配的,所以如果你也需要这些字段,就得延迟复制。

这是一种经过验证的可行方案。我想知道有没有更好的方法。

3

下面我列出了一些选项。如果你不需要在你的模型中处理那些对象,我建议你使用数据库触发器。

  • 使用数据库触发器来帮你完成这个工作。
  • 创建一个SessionExtension,它会在会话中创建并添加对象的副本(通常是在before_flush之前)。编辑-1:你可以参考版本控制示例作为基础;这段代码做的事情比你需要的还要多。
  • 查看SA版本控制示例,它不仅会给你对象的副本,还会提供完整的版本历史,这可能正是你想要的。
  • 查看从表到模型的反向映射问题,里面描述了一个解决方案,详细信息可以在这篇博客中找到。

撰写回答