一、gorm安装
1.下载gorm
go get -u gorm.io/gorm //gorm框架
go get -u gorm.io/driver/mysql //驱动
2.mysql准备工作
mysql> create database godb;
mysql> grant all on *.* to 'admin'@'%' identified by 'golang123!';
mysql> flush privileges;
3.导入gorm框架
import (
"gorm.io/gorm"
"gorm.io/driver/mysql"
)
4.连接mysql
这里单独创建一个连接mysql的包,
package mysqldb
import (
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
func Mysql_connect() *gorm.DB {
dsn := "admin:golang123!@tcp(192.168.1.23:3306)/godb?charset=utf8mb4&parseTime=True&loc=Local"
db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})
return db
}
5.引入连接包函数
package main
import (
"fmt"
"gorm/mysqldb"
)
func main() {
db := mysqldb.Mysql_connect()
fmt.Println(db)
}
此时如果没有报错,说明连接mysql已经成功了
二、基本使用
1.创建和表对应的结构体
这里新建了一个db.go 也属于mysqldb包
package mysqldb
import "time"
//共用结构体,其它结构体直接继承即可,字段是所有表共用字段,所有做一个基础结构体,减少重复定义。
//反撇号中的内容是"标签"。标签的含义结构体转换成另外一种格式的时候,传递过去一些信息
//其实在gorm中有一个自带的gorm.Model结构体,和这里自建的BaseModule 基本一致
type BaseModule struct {
Id int `gorm:"primarykey"`
CreateTime *time.Time `gorm:"autoCreateTime"`
UpdateTime *time.Time `gorm:"autoCreateTime"`
}
//创建老师表
type Teacher struct {
BaseModule //继承共用结构体,这里使用了匿名字段,使用数据类型(结构体类型)作为字段名称
Name string `gorm:"type:varchar(32);unique;not null"`
Tno int //账号
Pwd string //密码
Tel string //电话
}
2.teacher表
在main.go中开始初始Teacher表
package main
import (
"gorm/mysqldb"
)
func main() {
db := mysqldb.Mysql_connect()
//开始初始化表
db.AutoMigrate(&mysqldb.Teacher{})
}
查看数据库内容teachers表已经创建好。这里可以看到 BaseModel 不用初始化为数据库表。teacher表中也会继承了它的字段
mysql> use godb
Database changed
mysql> show tables;
+----------------+
| Tables_in_godb |
+----------------+
| teachers |
+----------------+
1 row in set (0.00 sec)
mysql> desc teachers;
+-------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+----------------+
| id | bigint(20) | NO | PRI | NULL | auto_increment |
| create_time | datetime(3) | YES | | NULL | |
| update_time | datetime(3) | YES | | NULL | |
| name | varchar(32) | NO | UNI | NULL | |
| tno | bigint(20) | YES | | NULL | |
| pwd | longtext | YES | | NULL | |
| tel | longtext | YES | | NULL | |
+-------------+-------------+------+-----+---------+----------------+
7 rows in set (0.00 sec)
2.1 手动插入数据
这里手动插入数据。ID列是自增长列,在手动插入数据的时候写NULL就可以了。两个时间字段用now()函数就可以了
mysql>insert into teachers values(NULL,now(),now(),"teacher wang",3123,"wang!","13312312311");
mysql> select * from teachers;
+----+-------------------------+-------------------------+--------------+------+-------+-------------+
| id | create_time | update_time | name | tno | pwd | tel |
+----+-------------------------+-------------------------+--------------+------+-------+-------------+
| 1 | 2023-07-20 22:37:20.000 | 2023-07-20 22:37:20.000 | teacher wang | 3123 | wang! | 13312312311 |
+----+-------------------------+-------------------------+--------------+------+-------+-------------+
1 row in set (0.00 sec)
2.2 在次初始化
go run main.go
此时发现数据没有受到任何影响。
但是会重复生成: UNIQUE KEY. 通过show create table 表名查看
2.3 表名变复数
结构体的名称为teacher 但是创建的表变成了teachers 多了一个s 这是在迁移过程中库自己加的。如果不影响使用可以忽略。
3.class表
class表对应结构体如下
type Class struct {
BaseModule
Name string `gorm:"type:varchar(32);unique;not null"`
Num int
TId int
T Teacher
}
注意:
TId int
这个字段是外键字段,字段的值指向 teacher表的 id 字段值
T Teacher
这个成员变量不会在mysql中产生字段。这是设置的 TId字段的 外键关联语句,相当于 foreign key 字段名 refences 主表(id)
1.T的意思是:gorm会根据这个名字(T)自动在后边加上Id,然后在结构体中找这个变量,并且将这个字段设置为外键。 也就是说 T = TId. 如果你的外键字段在命名时,那将设置外键关联失败
2.Teacher的意思是: 它是Teacher表, gorm在管理的时候 会自动关联到Teacher的ID字段
这中简写方式是gorm 提供的语法糖
1.开始迁移
package main
import (
"gorm/mysqldb"
)
func main() {
db := mysqldb.Mysql_connect()
db.AutoMigrate(&mysqldb.Class{})
}
2.查看表
mysql> show tables;
+----------------+
| Tables_in_godb |
+----------------+
| classes |
| teachers |
+----------------+
2 rows in set (0.00 sec)
mysql> desc classes;
+-------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+----------------+
| id | bigint(20) | NO | PRI | NULL | auto_increment |
| create_time | datetime(3) | YES | | NULL | |
| update_time | datetime(3) | YES | | NULL | |
| name | varchar(32) | NO | UNI | NULL | |
| num | bigint(20) | YES | | NULL | |
| t_id | bigint(20) | YES | MUL | NULL | |
+-------------+-------------+------+-----+---------+----------------+
6 rows in set (0.00 sec)
mysql> show create table classes;
| classes | CREATE TABLE `classes` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`create_time` datetime(3) DEFAULT NULL,
`update_time` datetime(3) DEFAULT NULL,
`name` varchar(32) NOT NULL,
`num` bigint(20) DEFAULT NULL,
`t_id` bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`),
KEY `fk_classes_t` (`t_id`),
//这里已经创建好了外键关联
CONSTRAINT `fk_classes_t` FOREIGN KEY (`t_id`) REFERENCES `teachers` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
三、新增数据
1.Teacher表新增数据
package main
import (
"gorm/mysqldb"
"gorm.io/gorm"
)
func Insert(db *gorm.DB) {
t1 := mysqldb.Teacher{Name: "wang", Tno: 1, Pwd: "123!", Tel: "11012341235"}
db.Create(&t1)
}
func main() {
db := mysqldb.Mysql_connect()
Insert(db)
}
1.1.注意事项1
t1 := mysqldb.Teacher{Name: "wang", Tno: 1, Pwd: "123!", Tel: "11012341235"}
实例化的时候使用键值对的方式赋值,不要使用{"wang",1,"123!","11012341235"}这种方式,因为我们继承了BaseModule
1.2.注意事项2
db.Create(&t1)
在新增数据的时候,一定要传入结构体实例的指针,因为gorm要把主键值回写到结构体实例
1.3 新增结果
这里可以看到,在新增的的时候,没有新增BaseModule的数据,但是在数据里自动生成了。并且ID是自增长的
mysql> select * from teachers;
+----+-------------------------+-------------------------+------+------+------+-------------+
| id | create_time | update_time | name | tno | pwd | tel |
+----+-------------------------+-------------------------+------+------+------+-------------+
| 1 | 2023-08-03 10:21:03.551 | 2023-08-03 10:21:03.551 | wang | 1 | 123! | 11012341235 |
+----+-------------------------+-------------------------+------+------+------+-------------+
1 row in set (0.00 sec)
2.Class新增数据
func InsertClass(db *gorm.DB) {
c1 := mysqldb.Class{Name: "python", Num: 30, TId: 1}
db.Create(&c1)
}
插入数据如下:
mysql> select * from classes;
+----+-------------------------+-------------------------+--------+------+------+
| id | create_time | update_time | name | num | t_id |
+----+-------------------------+-------------------------+--------+------+------+
| 1 | 2023-08-08 13:35:01.489 | 2023-08-08 13:35:01.489 | python | 30 | 1 |
+----+-------------------------+-------------------------+--------+------+------+
1 row in set (0.00 sec)
2.1 插入多条数据
func InsertClass(db *gorm.DB) {
c2 := mysqldb.Class{Name: "java", Num: 30, TId: 1}
c3 := mysqldb.Class{Name: "go", Num: 30, TId: 1}
c4 := mysqldb.Class{Name: "shell", Num: 30, TId: 1}
class_list := []mysqldb.Class{c2, c3, c4}
db.Create(&class_list)
}
插入数据如下:
mysql> select * from classes;
+----+-------------------------+-------------------------+--------+------+------+
| id | create_time | update_time | name | num | t_id |
+----+-------------------------+-------------------------+--------+------+------+
| 1 | 2023-08-08 13:35:01.489 | 2023-08-08 13:35:01.489 | python | 30 | 1 |
| 2 | 2023-08-08 14:14:15.927 | 2023-08-08 14:14:15.927 | java | 30 | 1 |
| 3 | 2023-08-08 14:14:15.927 | 2023-08-08 14:14:15.927 | go | 30 | 1 |
| 4 | 2023-08-08 14:14:15.927 | 2023-08-08 14:14:15.927 | shell | 30 | 1 |
+----+-------------------------+-------------------------+--------+------+------+
四、单表查询
1.查询全部 db.Find()
func selectdata(db *gorm.DB) {
// 这里定义切片的含义:
// 1. 因为返回是多条数据,所以定义Class类型切片
// 2. db.find函数是根据这里result的类型来判定去库里查找对应的哪张表
var result []mysqldb.Class
// 将查询结果集回写到result切片当中
db.Find(&result)
for i, v := range result {
fmt.Println("i = ", i)
fmt.Println("v = ", v.Name)
}
}
执行结果如下:
E:\code\project\后端项目\go_project\gin框架学习>go run main.go
i = 0
v = python
i = 1
v = java
i = 2
v = go
i = 3
v = shell
2.查询单条
func selectdata(db *gorm.DB) {
//三个变量设置的都是结构体实例,不是切片,因为查询结果是一条。
var result mysqldb.Class
var result1 mysqldb.Class
var result2 mysqldb.Class
db.Take(&result) //获取第一条记录,没有指定排序字段
db.First(&result1) //获取第一条记录(主键升序)
db.Last(&result2) //获取最后一条记录,主键降序
fmt.Println("result = ", result)
fmt.Println("result1 = ", result1)
fmt.Println("result2 = ", result2)
}
3.where查询
注意: where条件查询的时候,条件参数不能直接写,必须使用? 然后在将参数传递给?
3.1.等值查询
func selectdata(db *gorm.DB) {
var result []mysqldb.Class
db.Where("Name = ?", "java").Find(&result)
fmt.Println("result = ", result)
}
3.2 大于查询
func selectdata(db *gorm.DB) {
var result []mysqldb.Class
db.Where("update_time > ?", "2023-08-08 13:40:00").Find(&result)
fmt.Println("result = ", result)
}
3.3 and
func selectdata(db *gorm.DB) {
var result []mysqldb.Class
db.Where("num = ? and name = ?", 30, "go").Find(&result)
fmt.Println("result = ", result)
}
4. db.select
查询结果返回部分字段,而不是全部字段.
func selectdata(db *gorm.DB) {
var result []mysqldb.Class
db.Select("Name,num").Where("num = ? and name = ?", 30, "go").Find(&result)
fmt.Println("result = ", result)
}
这里只返回了Name和Num两个字段,其他字段内容没有进行回写
5.db.Omit
除了Name和Num字段 其他的字段其全部返回
func selectdata(db *gorm.DB) {
var result []mysqldb.Class
db.Omit("Name,Num").Where("num = ? and name = ?", 30, "go").Find(&result)
fmt.Println("result = ", result)
}
五、更新
数据库数据如下:
mysql> select * from classes;
+----+-------------------------+-------------------------+--------+------+------+
| id | create_time | update_time | name | num | t_id |
+----+-------------------------+-------------------------+--------+------+------+
| 1 | 2023-08-08 13:35:01.489 | 2023-08-08 13:35:01.489 | python | 30 | 1 |
| 2 | 2023-08-08 14:14:15.927 | 2023-08-08 14:14:15.927 | java | 30 | 1 |
| 3 | 2023-08-08 14:14:15.927 | 2023-08-08 14:14:15.927 | go | 30 | 1 |
| 4 | 2023-08-08 14:14:15.927 | 2023-08-08 14:14:15.927 | shell | 30 | 1 |
+----+-------------------------+-------------------------+--------+------+------+
1.修改单个字段
将go 改为golang
这里的db.Model 是用来指定表对应的结构体。
func update_data(db *gorm.DB) {
db.Model(&mysqldb.Class{}).Where("id = ?", 3).Update("name", "golang")
}
修改成功
mysql> select * from classes where id = 3;
+----+-------------------------+-------------------------+--------+------+------+
| id | create_time | update_time | name | num | t_id |
+----+-------------------------+-------------------------+--------+------+------+
| 3 | 2023-08-08 14:14:15.927 | 2023-08-08 14:14:15.927 | golang | 30 | 1 |
+----+-------------------------+-------------------------+--------+------+------+
1 row in set (0.00 sec)
2.修改多个字段
注意这里用的是updates,上边用的是update
func update_data(db *gorm.DB) {
db.Model(&mysqldb.Class{}).Where("id = ?", 3).Updates(mysqldb.Class{Name: "c++", Num: 20})
}
修改成功文章来源:https://www.toymoban.com/news/detail-642130.html
mysql> select * from classes where id = 3;
+----+-------------------------+-------------------------+------+------+------+
| id | create_time | update_time | name | num | t_id |
+----+-------------------------+-------------------------+------+------+------+
| 3 | 2023-08-08 14:14:15.927 | 2023-08-08 14:14:15.927 | c++ | 20 | 1 |
+----+-------------------------+-------------------------+------+------+------+
1 row in set (0.00 sec)
3.更新表达式gorm.Expr
func update_data(db *gorm.DB) {
db.Model(&mysqldb.Class{}).Where("id = ?", 3).Update("num", gorm.Expr("num + 1"))
}
更改结果如下:文章来源地址https://www.toymoban.com/news/detail-642130.html
mysql> select * from classes;
+----+-------------------------+-------------------------+--------+------+------+
| id | create_time | update_time | name | num | t_id |
+----+-------------------------+-------------------------+--------+------+------+
| 1 | 2023-08-08 13:35:01.489 | 2023-08-08 13:35:01.489 | python | 30 | 1 |
| 2 | 2023-08-08 14:14:15.927 | 2023-08-08 14:14:15.927 | java | 30 | 1 |
| 3 | 2023-08-08 14:14:15.927 | 2023-08-08 14:14:15.927 | c++ | 21 | 1 |
| 4 | 2023-08-08 14:14:15.927 | 2023-08-08 14:14:15.927 | shell | 30 | 1 |
+----+-------------------------+-------------------------+--------+------+------+
4 rows in set (0.00 sec)
到了这里,关于gorm基本操作的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!