首页 > 数据库 >MySql操作指南3--使用 ORM (GORM) 访问 MySQL

MySql操作指南3--使用 ORM (GORM) 访问 MySQL

时间:2025-01-17 13:30:56浏览次数:3  
标签:-- 数据库 db ORM result MySql gorm User

昨天发布的内容,使用原生写法来访问mysql数据库,然而,在实际项目中,这种写法,不仅需要写sql语句来实现表的增删改查,可维护性低,不易实现对象化和组件化,今天风云用ORM对象关系映射方式再实现一遍。每种语言都有自己的ORM库,golang里叫GORM。

先来介绍一下它的概念

ORM(对象关系映射)的意义在于简化数据库操作,提高开发效率和代码的可维护性‌。通过将数据库表中的数据映射为编程语言中的对象,ORM使得开发者可以更加自然地处理数据库操作,降低了编写SQL语句的难度,提高了代码的可读性和可维护性‌12。

1、ORM的定义和基本概念

ORM(Object-Relational Mapping)是一种编程技术,用于将关系型数据库中的数据映射为面向对象编程语言中的对象。它通过描述对象和数据库之间映射的元数据,实现程序中的对象自动持久化到关系数据库中‌。开发者无需编写复杂的 SQL,即可通过操作对象完成数据操作。

ORM的优势

  1. 映射关系自动管理‌:ORM可以自动生成数据库表与对象之间的映射关系,减少了手动编写映射代码的工作量‌1。
  2. 对象化操作‌:ORM将数据库操作抽象为对象操作,使得开发者可以更加自然地处理数据库,提高了开发效率‌1。
  3. 减少错误‌:ORM可以自动生成SQL语句,降低了因手动编写SQL语句而导致的错误‌1。
  4. 提高可维护性‌:ORM可以自动更新映射关系,使得数据库结构的变更不会影响代码的正确性,提高了代码的可维护性‌1。
  5. 开发效率高:通过封装数据库操作,简化了增删改查等常见操作
  6. 代码可读性强:以对象的形式操作数据,代码更易理解。
  7. 数据库独立性:ORM 能屏蔽大部分数据库差异,方便切换数据库。
  8. ORM 的不足: 性能开销:封装层可能导致比原生 SQL 略低的性能。复杂查询限制:处理复杂查询时,可能不如原生 SQL 高效。

 2、安装与配置 GORM

在 Golang 项目中安装 GORM 及其 MySQL 驱动:

go get -u gorm.io/gorm

go get -u gorm.io/driver/mysql

配置数据库连接

以下代码展示了如何初始化 GORM 并连接到 MySQL 数据库。

package main

import (
	"fmt"
	"log"
	"time"

	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

type User struct {
	ID uint `gorm:"primaryKey"`

	Name string `gorm:"size:255"`

	Email string `gorm:"uniqueIndex;size:255"`

	CreatedAt time.Time
}

func autoMigrate(db *gorm.DB) {
	err := db.AutoMigrate(&User{})

	if err != nil {
		log.Fatalf("自动迁移失败: %v\n", err)
	}
	fmt.Println("表结构同步成功")
}

func main() {
	// 数据库连接字符串
	dsn := "netwindcloud:netwindcloud123@tcp(127.0.0.1:3306)/netwindcloud?charset=utf8mb4&parseTime=True&loc=Local"

	// 初始化 GORM
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})

	if err != nil {
		log.Fatalf("数据库连接失败: %v\n", err)
	}
	fmt.Println("成功连接到数据库")

	// db.AutoMigrate(&User1{})
	autoMigrate(db)
}

3、GORM 模型定义与数据库操作

3.1 模型定义

在 GORM 中,表结构通过结构体定义,结构体的字段映射到数据库中的列。

type User struct {
	ID uint `gorm:"primaryKey"`

	Name string `gorm:"size:255"`

	Email string `gorm:"uniqueIndex;size:255"`

	CreatedAt time.Time
}

字段标签的含义:

  • primaryKey:主键。
  • size:列的最大字符长度。
  • uniqueIndex:唯一索引。

3.2 自动迁移

使用 AutoMigrate 方法将模型结构同步到数据库。

func autoMigrate(db *gorm.DB) { // 自动迁移
	err := db.AutoMigrate(&User{}) // 执行自动迁移

	if err != nil { // 如果发生错误,则打印错误并退出程序
		log.Fatalf("自动迁移失败: %v\n", err)
	}
	fmt.Println("表结构同步成功")
}

3.3 数据库基本操作

插入数据

func createUser(db *gorm.DB) { // 创建数据
	user := User{Name: "Alice", Email: "alice@example.com"} // 创建一个用户对象

	result := db.Create(&user) // 插入数据

	if result.Error != nil { // 如果发生错误,则打印错误并退出程序

		log.Fatalf("插入数据失败: %v\n", result.Error)

	}

	fmt.Printf("插入成功,用户ID: %d\n", user.ID)
}

查询数据

func queryUsers(db *gorm.DB) { // 查询数据
	var users []User // 定义一个切片,用于存储查询到的用户数据

	result := db.Find(&users) // 查询所有用户数据

	if result.Error != nil { // 如果发生错误,则打印错误并退出程序

		log.Fatalf("查询数据失败: %v\n", result.Error)
	}

	for _, user := range users { // 遍历查询到的用户数据

		fmt.Printf("ID: %d, Name: %s, Email: %s\n", user.ID, user.Name, user.Email)
	}
}

更新数据

func updateUser(db *gorm.DB) { // 更新数据

	result := db.Model(&User{}).Where("name = ?", "Alice").Update("email", "newalice@example.com") // 更新指定条件的用户邮箱

	if result.Error != nil { // 如果发生错误,则打印错误并退出程序

		log.Fatalf("更新数据失败: %v\n", result.Error)

	}

	fmt.Printf("更新成功,影响行数: %d\n", result.RowsAffected)
}

删除数据

func deleteUser(db *gorm.DB) { // 删除数据
	result := db.Where("name = ?", "Alice").Delete(&User{})

	if result.Error != nil { // 如果发生错误,则打印错误并退出程序

		log.Fatalf("删除数据失败: %v\n", result.Error)

	}

	fmt.Printf("删除成功,影响行数: %d\n", result.RowsAffected)
}

4、GORM 的高级功能

4.1 关联关系

GORM 支持模型之间的关系,包括一对一、一对多和多对多。

一对多示例

type Post struct {
	ID uint

	Title string

	UserID uint
}

type User struct { // 用户结构体
	ID uint

	Name string

	Posts []Post `gorm:"foreignKey:UserID"`
}

预加载关联数据

func preloadData(db *gorm.DB) { // 预加载数据
	var users []User // 定义一个切片,用于存储查询到的用户数据

	db.Preload("Posts").Find(&users) // 使用Preload方法预加载Posts字段

	for _, user := range users { // 遍历查询到的用户数据

		fmt.Printf("User: %s, Posts: %v\n", user.Name, user.Posts)

	}
}

4.2 原生 SQL 支持

GORM 支持直接执行原生 SQL:

func rawSQL(db *gorm.DB) { // 原生 SQL
	// 执行原生 SQL
	rows, err := db.Raw("SELECT id, name FROM users WHERE email = ?", "example@example.com").Rows()

	if err != nil { // 如果发生错误,则打印错误并退出程序

		log.Fatalf("执行原生 SQL 失败: %v\n", err)

	}

	defer rows.Close() // 关闭结果集

	for rows.Next() { // 遍历结果集
		var id uint // 定义一个变量,用于存储查询到的用户 ID

		var name string // 定义一个变量,用于存储查询到的用户名

		rows.Scan(&id, &name) // 扫描结果集

		fmt.Printf("ID: %d, Name: %s\n", id, name)
	}
}

4.3 分页与排序

func paginateAndSort(db *gorm.DB) { // 分页和排序
	var users []User // 定义一个切片,用于存储查询到的用户数据

	db.Order("created_at desc").Limit(10).Offset(0).Find(&users) // 执行分页和排序

	for _, user := range users { // 遍历查询到的用户数据
		fmt.Printf("User: %s\n", user.Name)
	}
}

标签:--,数据库,db,ORM,result,MySql,gorm,User
From: https://blog.csdn.net/weixin_42998312/article/details/145126070

相关文章

  • 【Python】深入探讨Python中的单例模式:元类与装饰器实现方式分析与代码示例
    《PythonOpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门!解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界单例模式(SingletonPattern)是一种常见的设计模式,它确保一个类只有一个实例,并提供一个全局访问点。在Python中,实现单例模式的方式多种多样,包括......
  • Python魔法方法深度解析:解密 __call__、__new__ 和 __del__
    《PythonOpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门!解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界在Python中,魔法方法(MagicMethods)是一些特殊的方法,它们允许开发者定制对象的行为。这些方法前后由双下划线包围,如__init__、__str__、__call_......
  • LabVIEW桥接传感器数据采集与校准程序
    该程序设计用于采集来自桥接传感器的数据,执行必要的设置(如桥接配置、信号采集参数、时间与触发设置),并进行适当的标定和偏移校正,最终通过图表呈现采集到的数据信息。程序包括多个模块,用于配置通道、触发条件、数据采集和校准过程,确保数据的准确性和可靠性。详细说明:通道设......
  • LabVIEW实车四轮轮速信号再现系统
    开发了一个基于LabVIEW的实车四轮轮速信号再现系统。该系统解决现有电机驱动传感器成本高、重复性差、真实性差和精度低等问题,提供一种高精度、低成本的轮速信号再现解决方案。项目背景ABS轮速传感器在现代汽车安全系统中发挥着至关重要的作用。为保证其准确性和可靠性,需通......
  • FPGA 基于 Vivado 核的双口 RAM 设计与实现
    FPGA基于Vivado核的双口RAM设计与实现介绍双口RAM(Dual-portRAM)是一种支持两个独立端口同时进行读写操作的存储器。这种架构在需要高并发数据访问的系统中非常有用。Vivado提供了方便的IP核来快速实现双口RAM,适用于各种FPGA设计。应用使用场景信号处理......
  • 如何将数据库字符集改为中文,让今后所有的数据库都支持中文
    最后一行有我自己的my.ini文件数据库输入中文数据时会变为乱码,这个时候,我们为每个数据库设置字符集,太过于麻烦,为数据库单独设置重启后又会消失Setcharacter_set_database=’utf8’;Setcharacter_set_server=’utf8’;先查看当前数据库参数输入代码:Showvariableslik......
  • KMP算法
    KMP算法kmp算法主要解决的问题就是字符串匹配,本篇文章节选自我的LeetCode字符串,在此单独记录一下kmp算法题1:字符串匹配寻找匹配子串,并返回起始索引classSolution:defstrStr(self,haystack:str,needle:str)->int:start=-1i=0......
  • 【c++】【算法】【动态规划】最长公共子序列
    【c++】【算法】【动态规划】最长公共子序列//递归方式//最长公共子序//直接递归求最长公共子序长度intFindValue(conststring&X,conststring&Y,inti,intj){ if(i==0||j==0)return0; if(X[i]==Y[j])returnFindValue(X,Y,i-1,j-1)+1; ......
  • 2025-01-17:构成整天的下标对数目Ⅰ。用go语言,给定一个整数数组 hours,其中每个元素表示
    2025-01-17:构成整天的下标对数目Ⅰ。用go语言,给定一个整数数组hours,其中每个元素表示以小时为单位的时间,要求返回一个整数,表示满足条件i<j且hours[i]+hours[j]为24的整数倍的下标对(i,j)的数量。这里,整天被定义为时间持续的时长是24小时的整数倍。例如,1天......
  • [rustGUI][iced]基于rust的GUI库iced(0.13)的部件学习(04):实现窗口主题(颜色)变换(暨menu菜单
    前言本文是关于iced库的部件介绍,iced库是基于rust的GUI库,作者自述是受Elm启发。iced目前的版本是0.13.1,相较于此前的0.12版本,有较大改动。本合集是基于新版本的关于分部件(widget)的使用介绍,包括源代码介绍、实例使用等。环境配置系统:window10平台:visualstudiocode语言:rust......