[小白入门指南] 如何使用gorm操作MySQL

81 阅读7分钟

1. 使用gorm的前置条件

1.1 MySQL的安装和配置

Debian中安装MySQL | MySQL创建用户并授予权限

#用rpm查看是否安装了MySQL
rpm -qa | grep mysql

#用ps命令查看是否有MySQL进程
ps -ef | grep mysql

##########拓展小知识##############
linux系统基本上分两大类,RedHat系列和Debian系列。
RedHat系列:有Redhat、Centos、Fedora等。
Debian系列:有Debian、Ubuntu等 。
RedHat 系列常见的安装包格式 rpm包,安装rpm包的命令是“rpm -参数”。
    包管理工具 yum。
    支持tar包 。
Debian系列常见的安装包格式 deb包,安装deb包的命令是“dpkg -参数”。
    包管理工具 apt-get。
    支持tar包 。


sudo systemctl status mysql                                    查看 mysql 状态mysql -u root -p              密码:123456                      更改为账号密码登录方式CREATE USER 'username1'@'%' IDENTIFIED BY 'password1';         创建用户GRANT ALL ON db1.* TO username1@'%' WITH GRANT OPTION;         给用户赋予权限

1.2 Naviacte For MySQL 16

navicat for mysql 16 无限试用

1.win+R打开运行,输入 regedit 打开注册表

2.HKEY_CURRENT_USER\SOFTWARE\PremiumSoft\Navicat\Registration16XCS 删除 Registration16XCS 中所有的内容, Registration16XCS不删除

3.如果存在 HKEY_CURRENT_USER\SOFTWARE\PremiumSoft\Navicat\Update 删除 Update

4.HKEY_CURRENT_USER\Software\Classes\CLSID{xxx-xxx-xxx-xxx-xxx} 找到一个包含Info的 , 删除 Info

2. gorm基本操作

gorm官方文档见文末。

2.1 添加

默认值

可以通过设置default标签设置默认值,设置了该标签会填充值为零值的字段。若要在迁移时跳过默认值定义,你可以使用 default:(-)

注意
对于声明了默认值的字段,像 0、''false 等零值是不会保存到数据库。您需要使用指针类型或 Scanner/Valuer 来避免这个问题,

创建记录

创建记录的几种方法: Create方法的参数可以是结构体指针也可以是结构体值类型,官方的例子都是使用的指针类型。

  • 使用对象指针创建:db.Create(&user)

  • 指定字段创建记录,未指定的字段为null:db.Select("Name", "Age", "CreatedAt").Create(&user)

  • 忽略指定的字段创建记录,被忽略的设置为null:db.Omit("Name", "Age", "CreatedAt").Create(&user)

  • 批量插入,传入一个切片:db.Create(&users)

  • 分批批量插入,传入一个切片,可以指定每批的数量:db.CreateInBatches(users, 100)

  • 根据map创建(好处是可以不用创建对象,更方便。但是参数的传递很不方便。比较适合后端批量插入):

    db.Model(&User{}).Create(map[string]interface{}{ "Name": "jinzhu", "Age": 18, }) // batch insert from []map[string]interface{}{} db.Model(&User{}).Create([]map[string]interface{}{ {"Name": "jinzhu_1", "Age": 18}, {"Name": "jinzhu_2", "Age": 20}, })

  • 使用SQL表达式、Context Valuer 创建记录(未记录)

高级选项

  • 钩子操作:GORM 允许用户定义的钩子有 BeforeSave, BeforeCreate, AfterSave, AfterCreate 创建记录时将调用这些钩子方法,请参考 Hooks 中关于生命周期的详细信息 如果您想跳过 钩子 方法,您可以使用 SkipHooks 会话模式,例如:

    DB.Session(&gorm.Session{SkipHooks: true}).Create(&user)

  • 关联创建:创建关联数据时,如果关联值是非零值,这些关联也会被创建,且他们的Hook方法也会被调用

    type CreditCard struct { gorm.Model Number string UserID uint } type User struct { gorm.Model Name string CreditCard CreditCard } db.Create(&User{ Name: "jinzhu", CreditCard: CreditCard{Number: "411111111111"} }) // INSERT INTO users ... // INSERT INTO credit_cards ...

  • Upsert及冲突(未记录)

2.2 查找

指定查询字段

使用Select()指定检索的字段,默认检索所有字段。

查询形式

  • 通过gorm提供的函数直接获取,比如First()Last()

  • String条件:使用Where()函数进行条件判断,参数通过 String 提供

  • Struct & Map条件:使用Where()函数进行判断,参数通过Struct 或 Map提供。使用struct时, 对零值(0,'',false等)不进行查询。

查询方法

  • 查询单条记录:First()(主键升序第一条)、Last()(主键降序第一条)、Take()(没有指定排序字段)。 没有找到记录时,它会返回 ErrRecordNotFound 错误。函数参数需要为结构体的指针类型或者使用db.model() 指定model才能生效。如果model没有指定主键,那么将按照model的第一个字段排序。

  • 根据主键获取

    db.First(&user, 10)// SELECT * FROM users WHERE id = 10;db.Find(&users, []int{1,2,3})// SELECT * FROM users WHERE id IN (1,2,3);// 如果主键是字符串db.First(&user, "id = ?", "1b74413f-f3b8-409f-ac47-e8c062e3472a")// SELECT * FROM users WHERE id = "1b74413f-f3b8-409f-ac47-e8c062e3472a";

  • 检索全部对象:db.Find()

查询筛选

  • 内联条件筛选:查询条件也可以内联到First()Find()之类的方法中,用法类似于Where(),可以使用String、Struct、Map方式提供查询条件

  • 非条件筛选Not()

  • 或条件筛选Or()

  • 排序筛选Order(),字段排序规则在Order函数中通过字符串选择

  • Limit & OffsetLimit()指定要检索的最大记录数。 Offset()指定在开始返回记录前要跳过的记录数。

  • Group By & Having:分组筛选和条件筛选

  • Distinct:从model中选择特定的值

  • Joins:(未记录)

  • Joins 预加载:(未记录)

  • Joins 一个衍生表:(未记录)

  • ScanScan() 结果至 struct,用法与 Find 类似

2.3 更新

更新方法

  • 保存所有字段Save 会保存所有的字段,即使字段是零值

    db.First(&user)user.Name = "jinzhu 2"user.Age = 100db.Save(&user)// UPDATE users SET name='jinzhu 2', age=100, birthday='2016-01-01', updated_at = '2013-11-17 21:34:10' WHERE id=111;

  • 更新单个列:当使用 Update 更新单个列时,你需要指定条件,否则会返回 ErrMissingWhereClause 错误。 当使用了 Model 方法,且该对象主键有值,该值会被用于构建条件。

  • 更新多列Updates 方法支持 structmap[string]interface{} 参数。当使用 struct 更新时,默认情况下,GORM 只会更新非零值的字段。 如果想要确保指定字段被更新,应该使用Select更新选定字段,或使用map来完成更新操作。

  • 更新选定字段Select选定更新字段,Omit选定忽略字段。

  • 更新Hook:对于更新操作,GORM 支持 BeforeSaveBeforeUpdateAfterSaveAfterUpdate 钩子。

  • 批量更新:不使用model指定主键则进行批量更新。没有任何条件的情况下gorm默认不会执行批量更新,对此 可以通过1.加一些条件 2.使用原生SQL 3.启用AllowGlobalUpdate模式来开启批量更新。例如:

    db.Model(&User{}).Update("name", "jinzhu").Error // gorm.ErrMissingWhereClausedb.Model(&User{}).Where("1 = 1").Update("name", "jinzhu")// 1.通过加条件解决 UPDATE users SET name = "jinzhu" WHERE 1=1 db.Exec("UPDATE users SET name = ?", "jinzhu")// 2.通过原生SQL解决 UPDATE users SET name = "jinzhu"db.Session(&gorm.Session{AllowGlobalUpdate: true}).Model(&User{}).Update("name", "jinzhu")// 3.通过开启AllowGlobalUpdate模式解决 UPDATE users SET name = "jinzhu"

  • 高级选项

    • 使用SQL表达式更新(未记录)

    • 使用子查询进行更新

    • 不使用Hook和时间追踪:如果您想在更新时跳过 Hook 方法且不追踪更新时间,可以使用 UpdateColumnUpdateColumns,其用法类似于 UpdateUpdates

    • 返回修改行的数据:可以更新数据并将选定的字段赋值给对象,不指定字段则默认全部。

    • 检查字段是否有变更Changed方法,它可以被用在 Before Update Hook 里, Changed 方法只能与 UpdateUpdates 方法一起使用, 并且它只是检查字段本身的值与更改之后的值是否相同,如果不同,且字段没有被忽略,则返回 true,反之返回false

    • Update时修改值:若要在 Before 钩子中改变要更新的值,如果它是一个完整的更新,可以使用 Save;否则,应该使用 SetColumn

2.4 删除

  • 删除一条记录:Delete,删除时需要指定主键,否则会批量删除

  • 根据主键删除:

2.5 gorm迁移

迁移过程中自定义类型的迁移参考:

Go gorm| MySQL不支持数组/切片怎么办?

GORM 字段使用自定义类型

gorm官方文档[1]

参考资料

[1]

gorm官方文档:

gorm.io/zh\_CN/