ORM是不是必要?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ORM是不是必要?相关的知识,希望对你有一定的参考价值。
参考技术AORM可以防止注入作为附加功能,SQL也可以带来反注入机制。ORM的主要作用是将数据库域的对象映射到面向对象的域中,因为开发人员更熟悉它们。
开发人员在开发时更倾向于用对象的方式思考
而他们更熟悉的用户有很多问题,而不是行、列和外键。面向对象的好处是在业务级重用,包括关联和业务逻辑。以上是OLTP和OLAP可能不同。使用ORM做OLAP分析不会有什么违反的感觉。虽然大多数ORM工具还提供接口,如组,加入和总和,ActiveRecord实际上提供了内在的连接,它必须拼左连接和交叉连接,但它实际上并没有多大的帮助。
直接写作是最简单、最直接的方法。
因为在OLAP应用程序中,思维不是面向对象的,而是面向主题、维度和度量的核心。
ORM的基本含义是将这个抽象结构暴露到应用程序代码中。
当您直接访问数据库时,结构是外部的,在文档内部和程序员的头脑中。代码中没有物理对应关系。ORM为您提供了物理结构。具体来说,当ORM时,您处理字段通信,当您使用SQL直接操作时,这很明显,您使用大脑将业务逻辑与SQL相匹配。
另一种方法是
通过ORM,抽象被构造并输入到应用程序代码中,这样就可以在代码中直接实现许多必要的约束,这有助于正确性。 参考技术B工程上没有绝对必要的东西,但是工程上说,ORM是极有价值的东西。当年也有人觉得 ORM 浪费资源,思路不清晰,虽然用了 Hibernate ,还是直接写 SQL ,手工操作。
什么是ORM
ORM框架采用元数据来描述对象一关系映射细节,元数据一般采用XML格式,并且存放在专门的对象一映射文件中。
只要提供了持久化类与表的映射关系,ORM框架在运行时就能参照映射文件的信息,把对象持久化到数据库中。当前ORM框架主要有三种:Hibernate,iBATIS,EclipseLink。
ORM从未从数据库中逃脱。如果你无法逃脱,为什么还要坚持呢?
有时,使用编程语言(而不是SQL(我也走了弯路,由MS讲道linq和linqtosql使用)来实现的复杂的SQL查询后台非常困难,因此,为什么复杂性的问题会出现在2、3甚至N度.
它真的能减轻开发的工作量吗?对不起,这不是放松。直接使用SQL访问(JDBC或ADO.net)相对较重。但是,复杂性并不是专注于业务的逻辑实现,而是UI层和用户交互。
如何设计查询、传入参数到IQuery
配置层XML来编写SQL语句。该程序的主要业务不是集中在这些方面,而是只关注于接口(仅针对IQuery)。对于XML层,可以自动地编写代码、复杂的SQL或人工干预,以及关于UI的复杂查询可以手动处理。
最后:我觉得任何语言都是相通的吧,没有什么必要不必要。
参考技术CORM的好处是,您不必中断面向对象的过程来考虑SQL,并编写代码以使其平滑。但是缺点是有很多限制,有时不像SQL那样灵活。但是能够迁移到不同的数据库还有一个好处。
一.ORM的概念是必要的,但是物极必反
RM生成的SQL质量不高,与框架相关,高、低;同样与人相关的是,熟悉SQL的人通常有更高的代码质量,这是编写由C程序员编写的良好质量的C代码的一个很好的理由,这些代码是由理解硬件的C程序员编写的。
在单位时间上提高了ORM的生产质量和效率。我想说明这一点。至于你写ORM代码是否会不可避免的比人为的好,我就是消极的态度。特别是对我来说,我认为几乎不可能超过我的手工编码的ORM。
然而,ORM允许我将一些复杂工作的人力成本压缩到可以接受的程度。例如,我正在研究一个数据建模工具。如果手工编码,我想考虑是否有一个模式,是否有serials,特定的数据库,不同的语法变化,以及不同生成的不同生成的目的。我将为自己编写一堆编译过的代码,因为我有一个成熟的、易于使用的、质量控制的ORM工具,为什么不呢?至少我可以减少3 / 4的代码。
二.ORM最终也是执行sql语句
ORM是通过提供的接口完成的,使用ORM直接获取数据,返回的数据通常是经过封装后的,资源的使用必须大于原始的SQL,在显示的时候方便,对于一个对象和一个简单的没有太大区别的组合。ORM最终执行SQL语句,我觉得我只是在用一堆代码来生成一个字符串。不可否认,它在某些地方确实很好,比如保存、添加和修改,这是很方便的。重用希望是好的。如果我只是使用orm来拼写SQL语句,我就不会有太多的感觉。实际上,我也使用ORM,在后面我使用ORM,我的前台80%是原始SQL
三.CQRS 核心就是领域层和读取数据分离
CQRS实际上是DDD的着陆框架。查询不需要通过存储库路径,所以越快越好,例如,直接使用SQL选择直接读取数据库是最好的,最快的。可以省略命令部分,而不是使用应用程序层,但是如果项目很大,最好使用命令。
在实际开发中,我认为你应该敞开心扉,不要局限于规则。它是为简单、效率和实用性而设计的。所谓的标准也是为了这个目的。
显式 cursor.close() 的必要性
【中文标题】显式 cursor.close() 的必要性【英文标题】:Necessity of explicit cursor.close() 【发布时间】:2014-08-30 22:55:53 【问题描述】:有时,我会使用 connection.cursor()
而不是 ORM 执行原始查询(因为它绝对不是灵丹妙药)。
我注意到,在我使用完数据库后,在几个地方我不会显式调用cursor.close()
。到目前为止,这还没有导致任何错误或性能问题。我想知道如果不显式关闭光标,我可能会遇到什么样的问题,会出现什么问题?
据我了解,Django 中的connection
和cursor
遵循“Python 数据库API 规范v2.0”(PEP-249)。而且,根据它,每当调用__del__()
方法时,cursor
都会自动关闭。我想问题也可能是:是否有不调用的用例?
仅供参考,我使用的是 Python 2.7 和 Django 1.6.5。
【问题讨论】:
我猜这和***.com/questions/5669878/…这个问题很相似?? @AamirAdnan 谢谢,不完全 - 在发布之前看到它。我知道如何关闭光标。问题是不关闭它有多糟糕以及后果是什么。 【参考方案1】:Django 的cursor
类只是底层DB 的cursor
的包装器,因此保持cursor
处于打开状态的效果基本上与底层DB 驱动程序相关。
根据 psycopg2(psycopg2 是 Django 用于 PostgreSQL DB 的 DB 驱动程序)FAQ,它们的游标是轻量级的,但会缓存您使用游标对象进行的查询返回的数据,这可能会浪费内存:
游标是轻量级对象,不应创建大量游标 提出任何问题。但请注意,用于获取结果的游标 集合将缓存数据并与结果成比例地使用内存 设置大小。我们的建议是几乎总是创建一个新光标并 不再需要数据时立即处理旧数据(致电 close() 。)唯一的例外是紧循环,其中一个通常 对一大堆 INSERT 或 UPDATE 使用相同的光标。
Django 使用MySQLdb
作为 MySQL 的后端,它有几种不同类型的游标,包括一些实际上将其结果集存储在服务器端的游标。 MySQLdb
documentation for Cursor.close
指出,当你完成它们时关闭服务器端光标非常重要:
如果你使用服务器端游标,关闭是非常重要的 完成后和创建新光标之前的光标。
但是,这与 Django 无关,因为它使用 MySQLdb
提供的默认 Cursor
类,它将结果存储在客户端。让使用过的游标处于打开状态只会有浪费存储结果集使用的内存的风险,就像psycopg2
一样。游标上的close
method只是删除了对db连接的内部引用,并耗尽了存储的结果集:
def close(self):
"""Close the cursor. No further queries will be possible."""
if not self.connection: return
while self.nextset(): pass
self.connection = None
据我所知,Django 使用的所有其余后端(cx_oracle、sqlite3/pysqlite2)都遵循相同的模式;通过删除/重置存储的结果/对象引用来释放内存。 sqlite3 docs 甚至没有提到 Cursor
类有一个 close 方法,它只是在包含的示例代码中偶尔使用。
当__del__()
在cursor
对象上调用时,cursor
将被关闭是正确的,因此只有在您保持对@ 的长期引用时,才需要显式关闭是一个问题987654344@;例如一个 self.cursor
对象,您作为类的实例方法保留。
【讨论】:
但是,如果将游标重新用于第二个查询,它为第一个查询缓存的数据将不再被引用。因此,从某种意义上说,不必要地创建一大堆游标可能会适得其反,除非您专门删除使用过的游标。 @holdenweb 对,如果您要在短时间内进行一大堆查询,那么使用相同的光标可能是有意义的。如果您要进行查询,然后在将来某个未知的时间进行另一个查询,您可能应该关闭/删除游标,这样您就不会保留它用于缓存结果集的任何内存。跨度> 看来我们达成了暴力协议。 最近对 django (1.5+) 如何以原子方式处理事务的变化值得注意,尤其是在您经常使用原始查询的情况下。查看最新的开发文档:docs.djangoproject.com/en/dev/topics/db/transactionscontextlib.closing
将确保光标按预期关闭,同时代码看起来仍然很紧凑。【参考方案2】:
__del__
/.close()
:
-
不保证会调用
__del__
某些数据库不会在其__del__
中调用 cursor.close()(不好的做法,但确实如此)
有些数据库实际上并没有在连接函数中创建连接,而是在游标函数中创建连接(例如,对于 2&3:pyhive 的 presto [也许他们已经修补了它])
一般在服务器连接上
大多数服务器都有一个空闲超时配置属性(我们称之为 T)。如果连接空闲超过 T 秒,服务器将删除该连接。大多数服务器还具有设置工作线程池 (W) 大小的属性。如果您已经有 W 连接到您的服务器,则在尝试新连接时它可能会挂起。再想象一下,您没有明确关闭连接的选项。在这种情况下,您必须将超时设置得足够小,以至于您的工作池永远不会被完全使用,这是您拥有多少并发连接的函数。
但是,如果您确实关闭了游标/连接(即使与上述 [3] 不等效,它们的行为也类似),那么您不必管理这些服务器配置属性,您的线程池只需要足够大以管理所有并发连接(可以选择偶尔等待新资源)。我已经看到一些服务器(例如 Cassandra 上的 Titan)无法从线程池中的工作线程用完中恢复,因此整个服务器在重新启动之前停止运行。
TL/DR
如果您使用的是非常完善的库,例如 dano
提到的那些,那么您不会有问题。如果您使用的原始库较少,如果您不调用 .close()
,最终可能会阻止服务器获取工作线程,具体取决于您的服务器配置和访问速率。
【讨论】:
【参考方案3】:虽然通常可以依靠操作系统来释放资源,但关闭数据库连接之类的东西以确保在不再需要时释放资源始终是一种良好的卫生习惯,从数据库的角度来看,真正重要的是确保任何更改都是commit()
ed。
【讨论】:
【参考方案4】:cursor.close()
的显式调用可能有两个原因:
__del__
不保证会被调用,并且有一些问题您可以阅读 here 和 here
显式优于隐式 (Zen of Python)
【讨论】:
【参考方案5】:这个问题我有点晚了。也许你想要一个关闭退出范围。
from contextlib import closing
from django.db import connection
with closing(connection.cursor()) as cursor:
cursor.execute(...)
cursor.execute(...)
cursor.execute(...)
【讨论】:
他们提到使用 Django 1.6 并且文档说上下文管理器(例如您的示例)直到 1.7 才明确添加,但是,文档似乎表明它在此之前以任何方式工作到“魔术方法查找中的意外行为”。以上是关于ORM是不是必要?的主要内容,如果未能解决你的问题,请参考以下文章