作为一个希望从手工编写的PHP站点迁移到基于框架的站点的Web开发人员,我已经看到很多关于一个ORM优于另一个ORM的讨论.它似乎对某些(?)大小的项目很有用,对企业级应用程序更为重要.
作为开发人员,它给了我什么?我的代码与我现在使用的各个SELECT语句有何不同?它如何帮助数据库访问和安全性?它如何找到有关数据库架构和用户凭据的信息?
编辑: @duffymo指出了对我来说应该是显而易见的:ORM仅对OOP代码有用.我的代码不是OO,所以我没有遇到ORM解决的问题.
我会说,如果你不处理对象,那么使用ORM就没什么意义了.
如果关系表/列使用对象/属性映射1:1,则使用ORM没有多大意义.
如果您的对象与其他对象没有任何1:1,1:m或m:n关系,则使用ORM没有多大意义.
如果你有复杂的,手动调整的SQL,那么使用ORM并没有多大意义.
如果您已确定数据库将存储过程作为其接口,则使用ORM没有多大意义.
如果您有一个无法重构的复杂遗留模式,那么使用ORM并没有多大意义.
所以这是相反的:
如果你有一个实体对象模型,对象之间的关系是1:1,1:m和m:n,那么就没有存储过程,就像ORM解决方案给你的动态SQL一样使用ORM.
像这样的决定总是一个选择.选择,实施,衡量,评估.
ORM正在被大肆宣传为数据访问问题的解决方案.就个人而言,在企业项目中使用它们之后,它们远远不是企业应用程序开发的解决方案.也许他们在小项目中工作.以下是我们遇到的问题,特别是nHibernate:
配置:ORM技术需要配置文件将表模式映射到对象结构中.在大型企业系统中,配置增长非常快,并且变得极难创建和管理.随着业务需求和模型在敏捷环境中不断变化和发展,维护配置也变得乏味且难以维护.
自定义查询:框架提供程序不支持或不推荐映射不适合任何已定义对象的自定义查询的功能.开发人员不得不通过编写adhoc对象和查询,或编写自定义代码来获取所需的数据来找到解决方法.他们可能不得不定期使用存储过程来处理比简单选择更复杂的事情.
Proprietery binding:这些框架需要使用在计算机科学行业中未标准化的专有库和专有对象查询语言.这些专有库和查询语言将应用程序绑定到提供程序的特定实现,在需要时很少或根本没有灵活性进行更改,并且没有相互协作的互操作性.
对象查询语言:提供称为对象查询语言的新查询语言,以对对象模型执行查询.它们会自动生成针对数据库的SQL查询,并从流程中抽象出用户.对于面向对象的开发人员来说,这似乎是一个好处,因为他们觉得编写SQL的问题已经解决了.实际问题是这些查询语言不能支持大多数现实世界应用程序所需的一些中高级SQL结构.它们还可以防止开发人员在必要时调整SQL查询.
性能:ORM层使用反射和内省来使用数据库中的数据实例化和填充对象.这些在处理方面是昂贵的操作并且增加了映射操作的性能降级.对象查询被转换为生成未优化的查询,而无需调整它们,从而导致显着的性能损失和数据库管理系统的过载.性能调优SQL几乎是不可能的,因为框架在控制自动生成的SQL方面提供的灵活性很小.
紧耦合:这种方法在模型对象和数据库模式之间产生了严格的依赖关系.开发人员不希望数据库字段和类字段之间存在一对一的关联.更改数据库模式会在对象模型和映射配置中产生波动影响,反之亦然.
缓存:此方法还需要使用对象缓存和上下文,这些对象缓存和上下文是维护和跟踪对象状态所必需的,并减少缓存数据的数据库往返.如果不在多层实现中维护和同步,这些高速缓存可能在数据准确性和并发性方面产生重大影响.通常需要插入第三方缓存或外部缓存来解决此问题,从而给数据访问层增加了大量负担.
有关我们分析的更多信息,请参阅:http: //www.orasissoftware.com/driver.aspx?topic =whitepaper
在非常高的层次上:ORM有助于减少对象 - 关系阻抗不匹配.它们允许您从关系数据库中存储和检索完整的活动对象,而无需自己进行大量的解析/序列化.
作为开发人员,它给了我什么?
对于初学者来说,它可以帮助你保持干爽.您可以使用模式或模型类是权威的,另一个是自动生成的,这样可以减少错误的数量和锅炉板代码的数量.
它有助于编组.ORM通常编组处理单个列到合适类型的值,这样你就不必解析/自己序列化.此外,它允许您从数据库中检索完全形成的对象,而不是简单地排列您必须包装自己的对象.
我的代码与我现在使用的各个SELECT语句有何不同?
由于您的查询将返回一个对象而并非只是行,您将能够访问使用属性访问,而不是创建一个新的查询相关的对象.您通常可以在需要时直接编写SQL,但对于大多数操作(CRUD),ORM将使与持久对象交互的代码更简单.
它如何帮助数据库访问和安全性?
一般来说,ORM有自己的API来构建查询(例如属性访问),因此不易受SQL注入攻击的影响; 但是,它们通常允许您将自己的SQL注入生成的查询中,以便在需要时可以执行奇怪的操作.这样注入的SQL你负责清理自己,但是,如果你不使用这些功能,那么ORM应该自动处理用户数据的清理工作.
它如何找到有关数据库架构和用户凭据的信息?
许多ORM都带有工具,可以检查模式并构建一组模型类,允许您与数据库中的对象进行交互.[数据库]用户凭证通常存储在设置文件中.
如果您手动编写数据访问层,那么您实际上是在编写自己的功能较差的ORM.
Oren Eini有一个很好的博客,总结了你在DAL/ORM中可能需要的基本功能,以及为什么写下你自己的功能在一段时间后成为一个坏主意:http: //ayende.com/Blog/archive/2006/05/12 /25ReasonsNotToWriteYourOwnObjectRelationalMapper.aspx
编辑:OP在其他答案中评论说他的代码库不是非常面向对象的.处理对象映射只是ORM的一个方面.该活动记录模式是怎样的ORM仍然情况下非常有用一个很好的例子对象映射1:1至表.
我不能代表其他ORM,只是Hibernate(对于Java).
Hibernate给了我以下内容:
在运行时自动更新生产系统上的表的架构.有时你仍然需要自己手动更新一些东西.
自动创建外键,使您无法编写创建孤立数据的错误代码.
实现连接池.可以使用多个连接池提供程序.
缓存数据以加快访问速度.可以使用多个缓存提供程序.这也允许您将许多服务器集群在一起以帮助您扩展.
使数据库访问更加透明,以便您可以轻松地将应用程序移植到另一个数据库.
使查询更容易编写.通常要求您三次写入"join"的以下查询可以这样写:
"来自Invoice i,其中i.customer.address.city =?" 这将检索具有特定城市的所有发票
返回一个Invoice对象列表.然后我可以调用invoice.getCustomer().getCompanyName(); 如果数据尚未在缓存中,则在后台自动查询数据库
您可以对数据库进行反向工程以创建hibernate架构(我自己没有尝试过),或者您可以从头开始创建架构.
当然,学习曲线与任何新技术一样,但我认为这是值得的.
在需要时,您仍然可以下拉到较低的SQL级别来编写优化的查询.
主要优点:
数据库抽象
以API为中心的设计心态
高水平==较少担心基础水平(它被认为适合你)
我不得不说,使用ORM实际上是数据库驱动的应用程序的演变.您不必担心您总是编写的样板SQL,而是更多地了解接口如何协同工作以构建一个非常简单的系统.
我不必担心INNER JOIN和SELECT COUNT(*).我只是在高级抽象中工作,同时我也在处理数据库抽象.
话虽如此,我从来没有真正遇到过这样一个问题:我需要在一个时间内在多个数据库系统上实际运行相同的代码.但是,这并不是说案例不存在,对于一些开发人员来说这是一个非常现实的问题.
使用的大多数数据库是关系数据库,它不直接转换为对象.对象关系映射器所做的是获取数据,使用实用程序函数在其周围创建一个shell,以便更新,删除,插入和执行其他操作.因此,不要将其视为行数组,而是现在有一个objets列表,您可以像操作任何其他对象一样操作,只需在完成后调用obj.Save().
我建议你看一下正在使用的一些ORM,我最喜欢的是python框架中使用的ORM,django.我们的想法是,您可以编写数据在数据库中的外观定义,ORM负责验证,检查以及在插入数据之前需要运行的任何机制.
就我个人而言,迄今为止我还没有使用过ORM技术的丰富经验.我目前正在为一家使用nHibernate的公司工作,我真的无法继续使用它.任何一天给我一个存储过程和DAL!更多代码确定...但更多的控件和代码更容易调试 - 根据我使用早期版本的nHibernate的经验,它必须添加.