ORM框架详解:为什么不直接写SQL?

打印 上一主题 下一主题

主题 824|帖子 824|积分 2472

想象一下,你正在开发一个小型的在线书店应用。你需要存储册本信息、用户数据和订单记录。作为一个初学者,你大概会想:“我已经学会了SQL,为什么还要利用ORM框架呢?直接写SQL语句不是更简单、更直接吗?”
假如你有雷同的疑问,那么恭喜你!你已经踏上了深入理解数据库交互的journey。在这篇文章中,我们将一起探索ORM框架的世界,相识它为什么存在,以及它怎样能够提升你的开发服从和代码质量。


  
什么是ORM框架?

ORM是"Object-Relational Mapping"的缩写,中文通常翻译为"对象关系映射"。这个术语听起来大概有点抽象,让我们通过一个简单的比喻来理解它:
想象你是一位翻译官,你的工作是在两种完全差别的语言之间进行翻译。在编程世界中,ORM就像如许一位翻译官,它在面向对象的编程语言(如Java、Python、C#等)和关系型数据库(如MySQL、PostgreSQL、Oracle等)之间进行"翻译"。
具体来说,ORM框架允许你:

  • 利用面向对象的方式来操作数据库
  • 将数据库表映射到编程语言中的类
  • 将表中的记录映射到类的实例(对象)
  • 将表的字段映射到对象的属性
通过这种映射,你可以利用认识的面向对象编程(OOP)概念和语法来进行数据库操作,而不需要直接编写SQL语句。

为什么需要ORM框架?

在答复这个问题之前,让我们先思索一下直接利用SQL大概会遇到的一些挑战:

  • 语言不匹配:SQL是一种声明式语言,而大多数编程语言是下令式的。这种范式的差异大概导致代码的不一致性和复杂性。
  • 代码重复:对于常见的CRUD(创建、读取、更新、删除)操作,你大概会发现自己在差别的地方重复编写相似的SQL语句。
  • 安全性问题:直接拼接SQL字符串容易导致SQL注入攻击,需要额外的注意和处理惩罚。
  • 数据库依赖:直接编写SQL会使你的代码与特定的数据库系统紧密耦合,难以切换到其他数据库。
  • 面向对象的不匹配:在面向对象的步伐中,你需要手动将SQL查询效果转换为对象,这个过程大概很繁琐。

ORM框架的出现就是为相识决这些问题。它提供了一个抽象层,使得开发者可以用面向对象的方式来操作数据库,从而提高开发服从,减少错误,并使代码更易于维护。
ORM vs 直接SQL:一个实际例子

让我们通过一个具体的例子来比较利用ORM和直接写SQL的区别。假设我们要实现earlier提到的在线书店应用中的一个功能:根据作者名称查询册本并更新代价。

直接利用SQL

  1. import mysql.connector
  2. # 连接数据库
  3. conn = mysql.connector.connect(
  4.     host="localhost",
  5.     user="yourusername",
  6.     password="yourpassword",
  7.     database="bookstore"
  8. )
  9. cursor = conn.cursor()
  10. # 查询书籍
  11. author_name = "J.K. Rowling"
  12. query = "SELECT id, title, price FROM books WHERE author = %s"
  13. cursor.execute(query, (author_name,))
  14. books = cursor.fetchall()
  15. # 更新价格
  16. for book in books:
  17.     book_id, title, current_price = book
  18.     new_price = current_price * 1.1  # 提高10%的价格
  19.     update_query = "UPDATE books SET price = %s WHERE id = %s"
  20.     cursor.execute(update_query, (new_price, book_id))
  21.     print(f"Updated price for '{title}' from {current_price} to {new_price}")
  22. # 提交事务并关闭连接
  23. conn.commit()
  24. cursor.close()
  25. conn.close()
复制代码
利用ORM(以SQLAlchemy为例)

  1. from sqlalchemy import create_engine, Column, Integer, String, Float
  2. from sqlalchemy.ext.declarative import declarative_base
  3. from sqlalchemy.orm import sessionmaker
  4. # 创建数据库引擎
  5. engine = create_engine('mysql://yourusername:yourpassword@localhost/bookstore')
  6. Base = declarative_base()
  7. # 定义Book模型
  8. class Book(Base):
  9.     __tablename__ = 'books'
  10.     id = Column(Integer, primary_key=True)
  11.     title = Column(String(100))
  12.     author = Column(String(50))
  13.     price = Column(Float)
  14. # 创建会话
  15. Session = sessionmaker(bind=engine)
  16. session = Session()
  17. # 查询和更新书籍
  18. author_name = "J.K. Rowling"
  19. books = session.query(Book).filter_by(author=author_name).all()
  20. for book in books:
  21.     book.price *= 1.1  # 提高10%的价格
  22.     print(f"Updated price for '{book.title}' from {book.price/1.1:.2f} to {book.price:.2f}")
  23. # 提交事务
  24. session.commit()
  25. session.close()
复制代码
通过比较这两段代码,我们可以看到利用ORM带来的一些显着上风:

  • 代码简便性:ORM版本的代码更加简便,不需要手动编写SQL语句。
  • 面向对象的操作:在ORM版本中,我们直接操作Book对象,这与面向对象编程的头脑更加一致。
  • 安全性:ORM自动处理惩罚参数化查询,减少SQL注入的风险。
  • 可读性:ORM代码更接近自然语言描述,更容易理解代码的意图。
  • 数据库无关性:假如需要切换到差别的数据库系统,只需要更改毗连字符串,而不需要重写SQL语句。
ORM的上风


通过上面的例子,我们已经看到了ORM的一些长处。让我们更系统地总结一下ORM框架的主要上风:

  • 生产力提升

    • 减少样板代码:ORM自动处理惩罚了很多底层的数据库操作,如毗连管理、SQL生成等。
    • 快速开发:利用ORM可以更快地构建数据模子和实行常见的数据库操作。

  • 面向对象的优雅

    • 自然的编程模子:ORM允许你用面向对象的方式思索和操作数据,这与大多数现代编程语言的范式一致。
    • 继承和多态:可以利用面向对象的特性来设计更机动、可扩展的数据模子。

  • 可维护性

    • 集中的数据模子定义:数据模子通常定义在一个地方,便于管理和修改。
    • 减少重复代码:常见的数据库操作被抽象化,减少了代码重复。

  • 数据库无关性

    • 易于切换数据库:大多数ORM支持多种数据库后端,切换数据库只需要更改配置。
    • 跨数据库的一致API:无论底层利用什么数据库,你都可以利用相同的API进行操作。

  • 安全性

    • 参数化查询:ORM自动利用参数化查询,大大低落SQL注入的风险。
    • 数据验证:很多ORM框架提供了数据验证功能,可以在数据进入数据库之进步行检查。

  • 性能优化

    • 延迟加载:ORM可以智能地决定何时从数据库加载数据,避免不须要的查询。
    • 缓存:一些ORM框架提供查询缓存功能,可以提高反复查询的性能。

  • 版本控制和迁移

    • 数据库迁移:很多ORM框架提供了数据库迁移工具,使得管理数据库schema的变更变得更加容易。
    • 版本控制:数据模子可以像其他代码一样进行版本控制。

  • 测试友爱

    • 易于模拟:利用ORM,你可以更容易地模拟数据库操作,便于单元测试。
    • 内存数据库:很多ORM支持内存数据库,可以加快测试过程。

ORM的潜在缺点

只管ORM框架带来了很多上风,但它也不是没有缺点。相识这些潜在的问题对于精确利用ORM非常告急:

  • 性能开销

    • 额外的抽象层:ORM在应用步伐和数据库之间增加了一个抽象层,这大概导致一些性能开销。
    • 大概生成次优的SQL:在复杂查询场景下,ORM生成的SQL大概不如手写的SQL优化。

  • 学习曲线

    • 新的概念:利用ORM需要学习新的概念和API,对于初学者来说大概有一定难度。
    • 配置复杂性:某些ORM框架的配置大概比较复杂,需要时间来把握。

  • "漏抽象"问题

    • 无法完全隐蔽SQL:在某些复杂查询场景下,你大概照旧需要编写原生SQL或相识底层的SQL知识。
    • 特定命据库功能:某些数据库特有的高级功能大概无法通过ORM直接利用。

  • 太过利用的风险

    • N+1查扣问题:假如不小心,很容易导致N+1查扣问题,影响性能。
    • 加载过多数据:假如不精确利用,大概会从数据库加载不须要的数据。

  • 调试困难

    • SQL不可见:由于SQL是动态生成的,调试复杂查询大概会变得困难。
    • 错误信息不清楚:ORM的错误信息偶然大概不如直接的SQL错误信息清楚。

  • 版本兼容性

    • ORM更新大概带来不兼容:ORM框架的主要版本更新大概需要修改现有代码。
    • 数据库驱动兼容性:ORM大概对特定版本的数据库驱动有依赖。


只管存在这些潜在的缺点,但对于大多数应用步伐来说,ORM的上风仍然宏大于缺点。关键是要理解这些限制,并在适当的时候做出衡量。
常见的ORM框架

差别的编程语言通常有其盛行的ORM框架。以下是一些主流编程语言中常用的ORM框架:

  • Python

    • SQLAlchemy:功能强盛、机动性高的ORM框架
    • Django ORM:Django web框架自带的ORM
    • Peewee:轻量级、简单易用的ORM

  • Java

    • Hibernate:最盛行的Java ORM框架之一
    • JPA (Java Persistence API):Java EE的ORM标准
    • MyBatis:一种"半自动"的ORM框架

  • C#/.NET

    • Entity Framework:微软官方的ORM框架
    • NHibernate:Hibernate的.NET移植版
    • Dapper:一个轻量级的ORM框架

  • Ruby

    • Active Record:Ruby on Rails框架中利用的ORM
    • Sequel:一个独立的Ruby ORM

  • JavaScript/Node.js

    • Sequelize:支持多种数据库的ORM
    • TypeORM:支持TypeScript的ORM
    • Mongoose:专门用于MongoDB的ODM(对象文档映射)

  • PHP

    • Doctrine:受Hibernate开导的PHP ORM
    • Eloquent:Laravel框架中利用的ORM


每个框架都每个框架都有其独特的特性和上风,选择哪一个通常取决于你的具体需求、项目规模、以及个人或团队的偏好。
怎样选择合适的ORM框架

选择合适的ORM框架对于项目标成功至关告急。以下是一些选择ORM框架时需要思量的因素:

  • 语言和生态系统兼容性

    • 确保ORM框架与你的主要编程语言有良好的集成。
    • 思量框架在该语言生态系统中的地位和受接待程度。

  • 学习曲线

    • 评估你和你的团队学习新框架所需的时间。
    • 思量框架的文档质量和社区支持。

  • 性能

    • 研究框架在处理惩罚大量数据时的性能表现。
    • 思量框架是否提供性能优化工具,如缓存机制。

  • 功能集

    • 确保框架支持你需要的全部数据库操作。
    • 检查是否支持高级功能,如复杂查询、事件管理等。

  • 数据库支持

    • 确保框架支持你计划利用的数据库系统。
    • 假如你需要支持多个数据库,检查框架的跨数据库能力。

  • 可扩展性

    • 思量框架是否能够随着项目标增长而扩展。
    • 检查是否支持分布式系统或微服务架构。

  • 社区和维护

    • 查看框架的GitHub星数、贡献者数量等指标。
    • 检查最近的更新频率,确保框架仍在积极维护。

  • 企业支持

    • 假如是企业级项目,思量是否有商业支持选项。

  • 与其他工具的集成

    • 检查框架是否能与你利用的其他开发工具良好集成。

  • 测试支持

    • 思量框架是否提供良好的测试支持,如易于模拟的API。


通过仔细衡量这些因素,你可以为你的项目选择最合适的ORM框架。记住,没有一个框架是完美的或恰当全部场景的,关键是找到最恰当你特定需求的办理方案。
实际应用:利用ORM构建在线书店后端

为了更好地理解ORM在实际项目中的应用,让我们用Python和SQLAlchemy来构建一个简单的在线书店后端。这个例子将展示怎样定义模子、实行查询、以及处理惩罚关系。
起首,我们需要安装须要的依赖:
  1. pip install sqlalchemy
复制代码
然后,我们可以开始编写我们的代码:
  1. from sqlalchemy import create_engine, Column, Integer, String, Float, ForeignKey
  2. from sqlalchemy.ext.declarative import declarative_base
  3. from sqlalchemy.orm import sessionmaker, relationship
  4. # 创建数据库引擎
  5. engine = create_engine('sqlite:///bookstore.db', echo=True)
  6. Base = declarative_base()
  7. # 定义模型
  8. class Author(Base):
  9.     __tablename__ = 'authors'
  10.     id = Column(Integer, primary_key=True)
  11.     name = Column(String(100), nullable=False)
  12.     books = relationship("Book", back_populates="author")
  13. class Book(Base):
  14.     __tablename__ = 'books'
  15.     id = Column(Integer, primary_key=True)
  16.     title = Column(String(100), nullable=False)
  17.     price = Column(Float, nullable=False)
  18.     author_id = Column(Integer, ForeignKey('authors.id'))
  19.     author = relationship("Author", back_populates="books")
  20. # 创建表
  21. Base.metadata.create_all(engine)
  22. # 创建会话
  23. Session = sessionmaker(bind=engine)
  24. session = Session()
  25. # 添加数据
  26. author1 = Author(name="J.K. Rowling")
  27. book1 = Book(title="Harry Potter and the Philosopher's Stone", price=19.99, author=author1)
  28. book2 = Book(title="Harry Potter and the Chamber of Secrets", price=21.99, author=author1)
  29. session.add(author1)
  30. session.add_all([book1, book2])
  31. session.commit()
  32. # 查询数据
  33. authors = session.query(Author).all()
  34. for author in authors:
  35.     print(f"Author: {author.name}")
  36.     for book in author.books:
  37.         print(f"  - {book.title} (${book.price:.2f})")
  38. # 更新数据
  39. book_to_update = session.query(Book).filter_by(title="Harry Potter and the Philosopher's Stone").first()
  40. if book_to_update:
  41.     book_to_update.price = 24.99
  42.     session.commit()
  43.     print(f"Updated price of '{book_to_update.title}' to ${book_to_update.price:.2f}")
  44. # 删除数据
  45. book_to_delete = session.query(Book).filter_by(title="Harry Potter and the Chamber of Secrets").first()
  46. if book_to_delete:
  47.     session.delete(book_to_delete)
  48.     session.commit()
  49.     print(f"Deleted '{book_to_delete.title}'")
  50. session.close()
复制代码
这个例子展示了怎样:

  • 定义数据模子(Author和Book)
  • 建立模子之间的关系
  • 创建数据库表
  • 添加、查询、更新和删除数据
通过这个简单的例子,我们可以看到ORM怎样简化数据库操作,使得代码更加直观和面向对象。
结论

ORM框架为开发者提供了一种强盛的工具,使得数据库操作变得更加简单、直观和安全。虽然直接编写SQL在某些环境下大概更简单或更高效,但ORM带来的利益通常超过了其潜在的缺点。
ORM的主要上风包罗:


  • 提高开发服从
  • 加强代码的可维护性
  • 提供数据库无关性
  • 加强应用步伐的安全性
  • 允许利用面向对象编程的上风
然而,利用ORM也需要衡量一些因素:


  • 大概带来一定的性能开销
  • 存在学习曲线
  • 在某些复杂查询场景大概不如直接SQL机动
对于大多数现代web应用步伐和企业系统来说,ORM已经成为了标准工具。它不但简化了开发过程,还提高了代码质量和可维护性。然而,像全部工具一样,ORM也不是全能的。理解ORM的工作原理、上风和局限性,才能在适当的场景下做出精确的选择。
末了,记住:ORM和SQL并不黑白此即彼的选择。在实际项目中,你大概会发现将ORM与原生SQL联合利用是最佳实践。大多数ORM框架都提供了实行原生SQL的能力,让你能够在需要时利用SQL的全部功能。

无论你选择利用ORM照旧直接编写SQL,告急的是要理解底层的数据库原理,如许你才能做出明智的决策,并在需要时进行优化。持续学习和实践将资助你在差别场景下选择最合适的工具和方法。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

魏晓东

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表