Flask SQLAlchemy 数据映射器与活动记录模式 [英] Flask SQLAlchemy Data Mapper vs Active Record Pattern

查看:18
本文介绍了Flask SQLAlchemy 数据映射器与活动记录模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近开始研究 Flask 和 Flask-SQLAlchemy.来自 Django 背景,我发现 Flask-SQLAlchmey 非常复杂.我读过 SQLAlchemy 实现了 Data Mapper 模式,而 Django ORM 基于 Active Record 模式.

I have recently started working on Flask and Flask-SQLAlchemy. Coming from Django background I found Flask-SQLAlchmey to be quite complex. I have read that SQLAlchemy implements Data Mapper pattern while Django ORM is based on Active Record Pattern.

这里是实现存储库模式以访问数据库的示例代码.

Here is a sample code written that implements repository pattern to access the database.

这里 是 S.Lott(271k 声誉)评论的另一个链接,他说 ORM 是数据访问层,它与模型分开.

Here is another link of a comment by S.Lott (271k reputation) who says that ORM is the data access layer and it is separate from model.

我的问题是:

  1. 您能否提供上述示例中的实际用例或您自己的示例,其中数据映射器模式很有用?我读到的所有地方都是数据映射器模式在复杂情况下很有用,但没有看到示例.
  2. 在上述情况下使用存储库模式是否与使用数据映射器模式相同?
  3. 数据映射器是否提倡在与示例中所做的模型不同的类中编写选择查询?
  4. 为什么 Question.query.filter_by(text = text).all() 不如使用db.session.query(Question).filter(Question.text == text).all()?
  1. Can you provide a practical use case in the above example or an example of your own where Data mapper pattern is useful? Everywhere I have read is that data mapper pattern is useful in complex situation, but not seen examples.
  2. Is using repositories pattern as in above case same as using a data mapper pattern?
  3. Does data mapper advocates write select queries in a different class than the model as done in the example?
  4. Why is Question.query.filter_by(text = text).all() not better to use than db.session.query(Question).filter(Question.text == text).all()?

这不是 DataMapper 与 ActiveRecord 的副本模式因为这只是说明定义,我对实际例子更感兴趣.

This is not a duplicate of DataMapper vs ActiveRecord pattern because this just tells the definition, I am more interested in the practical examples.

推荐答案

逐点.

我有一个旧数据库,我必须为其编写一些数据处理实用程序.使用 Mapper 模式,没有 ORM/ActiveRecord 样式,让我在编写查询时像 ActiveRecord 一样简单.它在类似于 SQL 子句的可组合对象上运行,不受 SQL 注入的影响.

I have a legacy database for which I have to write a few data-handling utilities. Using the Mapper pattern, without ORM / ActiveRecord style, made things for me about as easy when writing queries as ActiveRecord would. It is operating on nice composable objects that resemble SQL clauses, shielded from SQL injections.

被动"的对象允许更大的灵活性/统一性:复杂连接的结果是命名元组,就像简单选择的结果一样.没有要关心的身份,没有具有相同身份的缓存对象.

Objects being 'passive' allowed for more flexibility / uniformity: a result of a complex join is a named tuple, as is a result of a simple select. There's no identity to care about, no cached objects with the same identity.

所有更新都是明确的;不是保存"在别处更改的某些状态,没有在 .save() 上运行挂钩等.这使得高效的批量更新变得微不足道,如果将正确的数据发送到数据库,则不会出现问题.在我的情况下,两者都是好处.在一般情况下,视情况而定".例如,我必须在插入后手动获取数据库生成的 ID.显式运行此查询需要一些额外的工作.能够在一个查询中而不是每条记录中执行此操作对我来说是一个巨大的福音.

All updates are explicit; not a "save" of some state altered elsewhere, no hooks running on .save(), etc. This made efficient batch updates trivial, without troubling if the right data are sent to the DB. Both were benefits in my case. In general case, 'it depends'. For instance, I had to manually fetch database-generated IDs after inserts. Running this query explicitly is a bit of extra work. Being able to do that in one query instead of one per record was a huge boon in my case.

SQLAlchemy 具有分层设计,即使您在较高的 ORM 级别声明内容并正常对其进行操作,也允许您访问较低的映射器"级别.例如,在 Django 中,如果/何时仍然可能,它就不是那么简单了.

SQLAlchemy has a layered design that allows you to access the lower "mapper" level even if you declare things on upper ORM level and normally operate on it. In Django, for instance, it's not as straightforward if/when still possible.

在示例中,存储库"看起来像构建在映射器"之上的级别.存储库可以构建在普通 DBAPI 之上,但映射器使一些事情变得更简单,例如更好的参数绑定、结果集的命名元组,以及带有可组合、可重用部分的普通 SQL 之上的包装器.

In the example, the 'repository' looks like a level built above the 'mapper'. The repository could have been built on top of plain DBAPI, but the mapper makes a few things simpler, like nicer parameter binding, named tuples for the result sets, and a wrapper above plain SQL with composable, reusable parts.

映射器还提供了一定程度的数据库独立性.例如.SQL Server 和 Postgres 有不同的连接字符串的方法;映射器提供统一的接口.

The mapper also provides a certain degree of database independence. E.g. SQL Server and Postgres have different ways to concatenate strings; the mapper provides a unified interface.

您在使用它的地方编写select.如果你有一个你经常在不同上下文中重用的选择,你可以把它放到一个方法或函数中.大部分精选一用,即建即用.

You write your select where you use it. If you have a select that you constantly reuse in different contexts, you can put it into a method or function. Most of the selects have one use and are built on the spot.

SQLAlchemy 设计的一个很好的特性是,您可以轻松地存储条件和整个 where 子句,并在 select/update/delete 语句中重用它们.

A nice feature of SQLAlchemy's design is that you can easily store conditions and whole where clauses and reuse them across select / update / delete statements.

Question.query.filter_by(text = text).all() 使用隐式事务.db.session.query(Question).filter(Question.text == text).all() 使用显式事务.

Question.query.filter_by(text = text).all() uses an implicit transaction. db.session.query(Question).filter(Question.text == text).all() uses an explicit transaction.

显式事务让您放心使用 DML.当您查询快速变化的数据库并希望多个相关的 select 看到相同的一致状态时,它们对于 select 也很重要.

Explicit transactions give you a peace of mind with DML. They are important with selects, too, when you are querying a quickly changing database and want your several related selects see the same consistent state.

我通常围绕 sessionmaker 编写一个简单的包装器并编写如下内容:

I usually write a trivial wrapper around sessionmaker and write things like so:

with my_database.transaction() as trans:
   records = trans.query(...)
   ...
   updated = trans.execute(...).rowcount
# Here the transaction commits if all went well.

当我确定不应在此块中运行 DML 时,我使用了总是回滚的 .readonly_transaction().

When I definitely know no DML should run in this block, I use .readonly_transaction() that always rolls back.

在很多情况下,隐式事务是可以的.Django 允许你用 @transaction.atomic 装饰一个方法,并有一个半显式的事务控制,在 99% 的情况下就足够了.但有时您需要更细的粒度.

In many cases, the implicit transaction is fine. Django allows you to decorate a method with @transaction.atomic and have a semi-explicit transaction control, sufficient in 99% of cases. But sometimes you need even finer granularity.

这篇关于Flask SQLAlchemy 数据映射器与活动记录模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆