ORM 框架

ORM 框架ORM 是对象关系映射的缩写 用于解决面向对象编程与关系数据库之间的不匹配问题

大家好,欢迎来到IT知识分享网。

一. 什么是 orm 框架?

对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。ORM框架是连接数据库的桥梁,只要提供了持久化类与表的映射关系,ORM框架在运行时就能参照映射文件的信息,把对象持久化到数据库中。

二. 为什么使用ORM?

在最开始没有 orm 的时候,开发者们在开发过程种与数据库的交互常常避免不了以下步骤:

  • 手写 SQL
    • 问题
      • 容易出错
      • 难以重构
  • 手动处理结果集
    • 问题
      • 过多的样板代码
      • 开发者的将过多的精力投入到跟业务没关系的地方

如单纯的使用 database/sql 操作数据库如下

type TestModel struct { Id        int64 FirstName string Age       int8 LastName  *sql.NullString } ​ func Open(driver string, dsn string) (*sql.DB, error) { db, err := sql.Open(driver, dsn) if err != nil { return nil, err } return db, nil } ​ func main() { db, err := Open("mysql", "root:@tcp(localhost:3306)/integration_test") if err != nil { panic(err) } rows, err := db.QueryContext(context.Background(), "SELECT `id`,`first_name` FROM `test_model` LIMIT 1;") if err != nil { panic(err) } for rows.Next() { tm := &TestModel{} err = rows.Scan(&tm.Id, &tm.FirstName) if err != nil { panic(err) } fmt.Println(tm) } } ​

所以我们就希望有这么一个东西, 帮助我们完成这两个步骤,这也就 是 ORM 诞生的初衷。

三. ORM 框架主要职

ORM 框架

 

  • 对象 -> SQL

    当用户输入一个对象的时候,能够产生对应的 SQL。比如在插入场景下,一个 User 对象应该生成一条 INSERT INTO 语句

  • 结果集 -> 对象

    当收到数据库返回的行时,能 够将行组装成对象,并返回给用户。例如一条 SELECT 语句查出来一条数据,并将该数据组装 成一个 User 对象返回给用户

四. GO 主流的 ORM 框架

4.1 Beego orm

入门例子

package beego import ( "github.com/beego/beego/v2/client/orm" _ "github.com/mattn/go-sqlite3" "testing" ) ​ // User - type User struct { ID   int    `orm:"column(id)"` Name string `orm:"column(name)"` } ​ // 注册模型、驱动以及 DB func init() { // need to register models in init orm.RegisterModel(new(User)) ​ // need to register db driver orm.RegisterDriver("sqlite3", orm.DRSqlite) ​ // need to register default database orm.RegisterDataBase("default", "sqlite3", "beego.db") } ​ // 创建 ORM 实例 func TestCRUD(t *testing.T) { // automatically build table orm.RunSyncdb("default", false, true) ​ // create orm object o := orm.NewOrm() ​ // data user := new(User) user.Name = "mike" ​ // insert data o.Insert(user) }

源码解析

元数据

元数据是对模型的描述, 在 Beego 里分成了 modelInfo -> fields -> fieldInfo 三个层级

ORM 框架

ORM 框架

ORM 框架

查询接口

ORM 框架

ORM 框架 ORM 框架

ORM 框架

事务接口

事务接口分成两类:

  • 普通的 Begin、Commit 和 Rollback
  • 闭包形式的 DoXX

ORM 框架

ORM 框架 ORM 框架

4.2 Gorm

入门例子

package gorm ​ import ( "gorm.io/driver/sqlite" "gorm.io/gorm" "testing" ) ​ type Product struct { gorm.Model Code  string `gorm:"column(code)"` Price uint } ​ func (p Product) TableName() string { return "product_t" } ​ func (p *Product) BeforeSave(tx *gorm.DB) (err error) { println("before save") return } ​ func (p *Product) AfterSave(tx *gorm.DB) (err error) { println("after save") return } ​ func (p *Product) BeforeCreate(tx *gorm.DB) (err error) { println("before create") return } ​ func (p *Product) AfterCreate(tx *gorm.DB) (err error) { println("after create") // 刷新缓存 return } ​ func (p *Product) BeforeUpdate(tx *gorm.DB) (err error) { println("before update") return } ​ func (p *Product) AfterUpdate(tx *gorm.DB) (err error) { println("after update") // 刷新缓存 return } ​ func (p *Product) BeforeDelete(tx *gorm.DB) (err error) { println("before update") return } ​ func (p *Product) AfterDelete(tx *gorm.DB) (err error) { println("after update") return } ​ func (p *Product) AfterFind(tx *gorm.DB) (err error) { println("after find") return } ​ func TestCRUD(t *testing.T) { db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{}) if err != nil { panic("failed to connect database") } // 打印 SQL,但不执行 db.DryRun = true ​ // Migrate the schema db.AutoMigrate(&Product{}) ​ // Create db.Create(&Product{Code: "D42", Price: 100}) ​ ​ // Read var product Product db.First(&product, 1) // find product with integer primary key db.First(&product, "code = ?", "D42") // find product with code D42 ​ // Update - update product's price to 200 db.Model(&product).Update("Price", 200) // Update - update multiple fields db.Model(&product).Updates(Product{Price: 200, Code: "F42"}) // non-zero fields db.Model(&product).Updates(map[string]interface{}{"Price": 200, "Code": "F42"}) ​ // Delete - delete product db.Delete(&product, 1) }

源码解析

元数据

GORM 的元数据看起来和 Beego ORM元数据差不多,很难理解结构体里每一个字段的作用。 一个比较大的不同是 GORM 只有 Schame-> Field 两级。

ORM 框架

ORM 框架

查询接口ORM 框架

ORM 框架

ORM 框架  

事务接口

  • Begin、Commit、Rollback
  • 闭包接口
  • save point 支持

ORM 框架

4.3 Ent

Ent 和 Beego ORM、GORM 有一个设计理念上 的本质区别,就是 Ent 采用的是代码生成技术

ORM 框架

 

  • 入门例子
    package ent ​ import ( "context" "entgo.io/ent/dialect" "gitee.com/geektime-geekbang/geektime-go/orm/ent/ent" _ "github.com/mattn/go-sqlite3" "log" "testing" ) ​ func TestEntCURD(t *testing.T) { // Create an ent.Client with in-memory SQLite database. client, err := ent.Open(dialect.SQLite, "file:ent?mode=memory&cache=shared&_fk=1") if err != nil { log.Fatalf("failed opening connection to sqlite: %v", err) } defer client.Close() ctx := context.Background() // Run the automatic migration tool to create all schema resources. if err := client.Schema.Create(ctx); err != nil { log.Fatalf("failed creating schema resources: %v", err) } err = client.User.Create().Exec(context.Background()) }

五. ORM 核心功能模块

ORM 框架

 

  • SQL:必须要支持的就是增删改查,DDL 一般是作为 一个扩展功能,或者作为一个工具来提供。
  • 映射:将结果集封装成对象,性能瓶颈。
  • 事务:主要在于维护好事务状态。
  • 元数据:SQL 和映射两个部分的基石。
  • AOP:处理横向关注点。
  • 关联关系:部分 ORM 框架会提供,性价比低。
  • 方言:兼容不同的数据库,至少要兼容 MySQL、 SQLite、 PostgreSQL。

六. 总结

  • ORM 框架的核心是什么SQL 构造处理结果集。在别的语言里面,因为底层库可能不够强大, ORM 框架还要解决连接和会话管理的问题,Go 是不需要的。
  • ORM 是什么?ORM 是指对象关系映射,一般是指用于语言对象和关系型数据库行相互转化的工具
  • 为什么要使用 ORM 框架?本质上来说,不使用 ORM 框架也是可以的,但我们就要花费很多时间在处理拼接 SQL、处理返回的行上。这些本身是不难但很琐碎的事情,所以我们需要一个 ORM 框架来帮我们解决这两个问题。
  • ORM 的优点?ORM 的优点就是 API 对编程更加友好,开发效率更高。
  • 使用 ORM 性能会更好吗?显然不能,直接写 SQL 的性能最好。
  • ORM 怎么使用缓存?利用 AOP 来拦截到查询,而后嵌入缓存。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/113827.html

(0)
上一篇 2025-12-12 14:20
下一篇 2025-12-12 14:33

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信