Go framework-GORM

目录

一、GORM

1、GORM连接数据库

2、单表的增删改查

3、结构体名和表名的映射规则

4、gorm.Model匿名字段

5、结构体标签gorm

6、多表操作

7、常用方法

8、支持原生SQL

9、Gin整合GORM


一、GORM

        ORM:即Object-Relational Mapping,它的作用是在关系型数据库和对象之间作一个映射,这样,我们在具体的操作数据库的时候,就不需要再去和复杂的SQL语句打交道,只要像平时操作对象一样操作它就可以了。

        GORM:gorm是go语言的一个orm框架,Golang 写的,开发人员友好的 ORM 库。

安装GORM:

go get github.com/jinzhu/gorm

新建test_gorm项目

D:\GO_workspace_web>md test_gorm

D:\GO_workspace_web>cd test_gorm

D:\GO_workspace_web\test_gorm>go mod init test_gorm
go: creating new go.mod: module test_gorm

D:\GO_workspace_web\test_gorm>

使用GoLand打开项目,进入Terminal命令

PS D:\GO_workspace_web\test_gorm> go get github.com/jinzhu/gorm
go: downloading github.com/jinzhu/gorm v1.9.16
go: downloading github.com/jinzhu/inflection v1.0.0
go: added github.com/jinzhu/gorm v1.9.16
go: added github.com/jinzhu/inflection v1.0.0
PS D:\GO_workspace_web\test_gorm> 

1、GORM连接数据库

package main

import (
	_ "github.com/go-sql-driver/mysql" //引入mysql的驱动
	"github.com/jinzhu/gorm"
)

func main() {
	//连接数据库:
	//Open传入两个参数:
	//第一个参数:指定你要连接的数据库
	//第二个参数:指的是数据库的设置信息:用户名:密码@tcp(ip:port)/数据库名字?charset=utf8&parseTime=True&loc=Local
	//charset=utf8设置字符集
	//parseTime=True为了处理time.Time
	//loc=Local 时区设置,与本地时区保持一致
	db, err := gorm.Open("mysql", "root:root@tcp(localhost:3306)/testgorm?charset=utf8&parseTime=True&loc=Local")

	if err != nil {
		panic(err)
	}
	defer db.Close()
}

2、单表的增删改查

package main

import (
    "fmt"
	_ "github.com/go-sql-driver/mysql" //引入mysql的驱动
	"github.com/jinzhu/gorm"
)

func main() {
	db, err := gorm.Open("mysql", "root:root@tcp(localhost:3306)/testgorm?charset=utf8&parseTime=True&loc=Local")
	if err != nil {
		panic(err)
	}
	defer db.Close()
	db.CreateTable(&User{}) //创建表,默认表名后加s
    //db.Table("user").CreateTable(&User{}) //指定要创建的表名
    //flg1 := db.HasTable(&User{})  //判断是否有某张表
	//fmt.Println(flg1)
	flg2 := db.HasTable("users") //判断是否有某张表
	fmt.Println(flg2)
    //db.DropTable(&User{})  //删除表
    //db.DropTable("user")   //指定删除表名
	//增删改查
	//增加
	db.Create(&User{Name: "张无忌", Age: 30})
	//查询
	var muser User
	db.First(&muser, "age=?", 30)
	fmt.Println(muser)
	//更新:先查询再更新
	db.Model(&muser).Update("age", 40)
	fmt.Println(muser)
	db.Model(&muser).Update("name", "张翠山")
	fmt.Println(muser)
	//删除:先查询再删除
	db.Delete(&muser)
	fmt.Println(muser)
}

type User struct {
	Name string
	Age  int
}

3、结构体名和表名的映射规则

  1. 如果结构体名没有驼峰命名,那么表名就是:结构体名小写+复数形式: 如结构体名User-->表名users
  2. 如果结构体名有驼峰命名,那么表名就是:大写变小写并在前面加下划线,最后加复数形式:如结构体名UserInfo-->表名user_infos
  3. 如有结构体名有连续的大写字母,那么表名就是:连续的大写字母变小写,驼峰前加下划线,字母变小写,最后加复数形式:如结构体名:DBUserInfo-->表名db_user_infos
  4. 结构体中字段名称与表中列名的映射规则同上

自定义表名

package main

import (
	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/mysql"
)
type User struct {
	Age  int
	Name string
}
type UserInfo struct {
	Age  int
	Name string
}
type DBUserInfo struct {
	Age  int
	Name string
}
type MyUser struct {
	Age  int
	Name string
}
func (MyUser) TableName() string {//自定义表名
	return "test_my_user"
}
func main() {
	db, err := gorm.Open("mysql", "root:root@tcp(localhost:3306)/testgorm?charset=utf8&parseTime=True&loc=Local")
	if err != nil {
		panic(err)
	}
	defer db.Close()
	db.CreateTable(&User{})
	db.CreateTable(&UserInfo{})
	db.CreateTable(&DBUserInfo{})
	db.CreateTable(&MyUser{})
}

4、gorm.Model匿名字段

        只需要在自己的模型中指定gorm.Model匿名字段,即可在数据库表中包含四个字段:ID,CreatedAt,UpdatedAt,DeletedAt

ID:主键自增长
CreatedAt:用于存储记录的创建时间
UpdatedAt:用于存储记录的修改时间
DeletedAt:用于存储记录的删除时间

package main

import (
	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/mysql"
)

type MyTest struct {
	gorm.Model
	Age  int
	Name string
}

func main() {
	db, err := gorm.Open("mysql", "root:root@tcp(localhost:3306)/testgorm?charset=utf8&parseTime=True&loc=Local")
	if err != nil {
		panic(err)
	}
	defer db.Close()
	db.CreateTable(&MyTest{})
}

5、结构体标签gorm

通过结构体标签gorm来实现表的约束
gorm标签属性值:
(1)-: 忽略,不映射这个字段    eg: `gorm:"-"`  ,适合:一些冗余字段,不想在数据库中体现,只想在结构体中体现
(2)primary_key:主键     eg: `gorm:"primary_key"`
PS:如果是想要加联合主键,在每个字段后加入 `gorm:"primary_key"`即可
例如:即可将StuID和Name作为联合主键

StuID int `gorm:"primary_key"`
Name string `gorm:"primary_key"`

(3)AUTO_INCREMENT:自增    eg:  `gorm:"AUTO_INCREMENT"`
(4)not null:不为空,默认为空    eg: `gorm:"not null"`
(5)index:索引,  eg: `gorm:"index"`
创建索引并命名:eg: `gorm:"index:idx_name_code"`
(6)unique_index:唯一索引     eg: `gorm:"unique_index"`
唯一性索引unique index和一般索引normal index最大的差异就是在索引列上增加了一层唯一约束。添加唯一性索引的数据列可以为空,但是只要存在数据值,就必须是唯一的。
(7)unique:唯一   eg: `gorm:"unique"`
(8)column:指定列名   eg: `gorm:"column:user_name"`
(9)size:字符串长度,默认为255   eg:`gorm:"size:10"`
(10)default `default:'男'` 默认值
(11)type:设置sql类型  eg: `gorm:"type:int(2)"` 
PS:多个属性值之间用分号分隔

type Student struct {
	StuID   int    `gorm:"primary_key;AUTO_INCREMENT"`
	Name    string `gorm:"not null"`
	Age     int    `gorm:"unique_index"`
	Email   string `gorm:"unique"`
	Sex     string `gorm:"column:gender;size:10"`
	Desc    string `gorm:"-"`
	Classno string `gorm:"type:int"`
}

6、多表操作

6.1、一对一关系

//1、
type User struct{
        UserId int `gorm:"primary_key;AUTO_INCREMENT"`
        Age int
        Name string
}
type UserInfo struct {
        InfoID int `gorm:"primary_key;AUTO_INCREMENT"`
        Pic string
        Address string
        Email string
        //关联关系
        User User
        //指定外键
        UserId int
}

//2、通过gorm标签来指定外键:(属于关系:关系和外键的指定在同一方)
type User struct{
        UserId int `gorm:"primary_key;AUTO_INCREMENT"`
        Age int
        Name string
}
type UserInfo struct {
        InfoID int `gorm:"primary_key;AUTO_INCREMENT"`
        Pic string
        Address string
        Email string
        //关联关系
        User User `gorm:"ForeignKey:MyUserID;AssociationForeignKey:UserId"`
        //指定外键:
        MyUserID int
}

//3、通过gorm标签来指定外键:(包含关系:关系和外键的指定不在同一方)
type User struct {
	UserId int `gorm:"primary_key;AUTO_INCREMENT"`
	Age    int
	Name   string
	IID    int
}

type UserInfo struct {
	InfoID  int `gorm:"primary_key;AUTO_INCREMENT"`
	Pic     string
	Address string
	Email   string
	User    User `gorm:"ForeignKey:IID;AssociationForeignKey:InfoID"` //关联关系
}

操作:

6.2、一对多关系

type Author struct {
	AID int `gorm:"primary_key;AUTO_INCREMENT"`
	Name string
	Age int
	Sex string
	Article []Article `gorm:"ForeignKey:AuId;AssociationForeignKey:AID"`//关联关系
}

type Article struct {
	ArId int `gorm:"primary_key;AUTO_INCREMENT"`
	Title string
	Content string
	Desc string
	AuId int//设置外键
}

操作:

6.3、多对多关系

type Student struct {
	SId int `gorm:"primary_key"`
	SNo int
	Name string
	Sex string
	Age int
	Course []Course `gorm:"many2many:Student2Course"`//关联表
}

type Course struct {
	CId int `gorm:"primary_key"`
	CName string
	TeacherName string
	Room string
}

操作:

7、常用方法

【1】First:按照条件查询,并且升序排列,查询出一条记录
【2】FirstOrCreate:有数据就查询出来,没有就创建一条记录
【3】Last:按照条件查询,并且降序排列,查询出一条记录
【4】Take:按照条件查询,查询出一条记录
【5】Find:按照条件查询

package main

import (
	"fmt"
	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/mysql"
)

type User struct {
	UserId int `gorm:"primary_key;AUTO_INCREMENT"`
	Age    int
	Name   string
	IID    int
}

func main() {
	db, err := gorm.Open("mysql", "root:root@tcp(localhost:3306)/testgorm?charset=utf8&parseTime=True&loc=Local")
	if err != nil {
		panic(err)
	}
	defer db.Close()
	db.DropTable(&User{})
	db.CreateTable(&User{})
	//增加:Exec
	db.Exec("insert into users (age,name) values (?,?)", 18, "张无忌")
	//First:
	var user User
	db.Debug().First(&user, 1) //-->默认情况查询的是主键
	fmt.Println(user)
	db.Debug().First(&user, "user_id = ?", 1)
	fmt.Println(user)
	db.Debug().Where("user_id = ?", 1).First(&user)
	fmt.Println(user)

	//FirstOrCreate:SELECT * FROM `users`  WHERE `users`.`user_id` = 1 AND ((user_id = 1)) ORDER BY `users`.`user_id` ASC LIMIT 1
	user2 := User{ //这里定义的结构体的实例的数值其实就是FirstOrCreate的查询条件
		UserId: 2,
		Age:    20,
		Name:   "菲菲",
		IID:    1,
	}
	//如果有对应的数据,就查询出来,如果没有对应的数据,就会帮我们创建新的记录
	db.FirstOrCreate(&user, user2)
	fmt.Println(user)
	//Last:SELECT * FROM `users`  WHERE `users`.`user_id` = 2 AND ((`users`.`user_id` = 1)) ORDER BY `users`.`user_id` DESC LIMIT 1
	db.Debug().Last(&user, 1)
	fmt.Println(user)
	//Take:SELECT * FROM `users`  WHERE `users`.`user_id` = 2 AND ((`users`.`user_id` = 1)) LIMIT 1
	db.Debug().Take(&user, 1)
	fmt.Println(user)
	//Find:SELECT * FROM `users`  WHERE `users`.`user_id` = 2 AND ((`users`.`user_id` IN (1,2)))
	user_id_arr := []int{1, 2}
	db.Debug().Find(&user, user_id_arr)
	fmt.Println(user)
}

【6】Where:加入指定条件:
具体条件为:=,like,in,and,between....
【7】Select:筛选查询出来的字段
【8】Create:添加数据
【9】Save:添加数据
【10】Update:更新数据
【11】Delete:删除数据

package main

import (
	"fmt"
	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/mysql"
)

type User struct {
	UserId int `gorm:"primary_key;AUTO_INCREMENT"`
	Age    int
	Name   string
	IID    int
}

func main() {
	db, err := gorm.Open("mysql", "root:root@tcp(localhost:3306)/testgorm?charset=utf8&parseTime=True&loc=Local")
	if err != nil {
		panic(err)
	}
	defer db.Close()
	db.DropTable(&User{})
	db.CreateTable(&User{})
	//增加:Exec
	db.Exec("insert into users (age,name) values (?,?)", 18, "张无忌")
	//Where
	var user User
	db.Debug().Where("user_id = ?", 1).First(&user)
	fmt.Println(user)
	db.Debug().Where("user_id in (?)", []int{1, 2}).First(&user)
	fmt.Println(user)
	//Select
	db.Debug().Select("name,age").Where("user_id = ?", 1).First(&user)
	fmt.Println(user)
	//Create:操作只可以插入一条技能,不能批量操作
	user2 := User{
		Age:  26,
		Name: "小明",
		IID:  1,
	}
	db.Create(&user2)
	//Save
	user3 := User{
		Age:  14,
		Name: "莎莎",
		IID:  1,
	}
	db.Save(&user3)
	//Update更新:先查询再更新:
	var user4 User
	//(1)先查询,再通过Model进行操作,再Update操作:
	db.Where("user_id = ?", 1).First(&user4)
	db.Model(&user4).Update("age", 29)
	fmt.Println(user4)
	//(2)直接在查询之后进行操作:
	db.Where("user_id = ?", 1).First(&user4).Update("name", "露露")
	fmt.Println(user4)
	//(3)直接在查询之后进行操作,传入结构体示例,更新多个字段
	db.Where("user_id = ?", 1).First(&user4).Update(User{
		Age:  11,
		Name: "小刚",
	})
	fmt.Println(user4)
	//(4)直接在查询之后进行操作,传入map,更新多个字段
	db.Where("user_id = ?", 1).First(&user4).Update(map[string]interface{}{
		"age":  21,
		"name": "小花",
	})
	fmt.Println(user4)

	//Delete:删除数据:
	// (1)先查询再删除:
	var user5 User
	db.Where("user_id = ?", 1).First(&user5)
	db.Delete(&user5)
	//(2)通过条件直接进行删除:
	var user6 User
	db.Where("user_id = ?", 2).Delete(&user6)
}

【12】Not:排除某个具体条件的查询操作
【13】Or:多个条件的查询
【14】Order:进行升序或者降序的排列
【15】Limit:指定获取记录的最大数量
【16】Offset:设置偏移
【17】Scan:将结果扫描到另一个结构体中
【18】Count:计数
【19】GROUP:进行分组
【20】Having:分组后进行过滤

package main

import (
	"fmt"

	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/mysql"
)

type User struct {
	UserId int `gorm:"primary_key;AUTO_INCREMENT"`
	Age    int
	Name   string
	IID    int
}

func main() {
	db, err := gorm.Open("mysql", "root:root@tcp(localhost:3306)/testgorm?charset=utf8&parseTime=True&loc=Local")
	if err != nil {
		panic(err)
	}
	defer db.Close()
	db.DropTable(&User{})
	db.CreateTable(&User{})
	//增加:Exec
	db.Exec("insert into users (age,name) values (?,?)", 28, "张无忌")
	db.Exec("insert into users (age,name) values (?,?)", 26, "赵敏")
	db.Exec("insert into users (age,name) values (?,?)", 25, "小昭")
	//Not:
	var users []User
	db.Not("user_id = ?", 1).Find(&users)
	fmt.Println(users)
	var users1 []User
	db.Debug().Not(User{
		Age:  18,
		Name: "丽丽",
	}).Find(&users1)
	fmt.Println(users1)
	//Or :
	var users2 []User
	db.Where("user_id = ?", 1).Or("user_id = ?", 3).Find(&users2)
	fmt.Println(users2)
	//Order:
	var users3 []User
	db.Where("age = ?", 26).Order("user_id asc").Find(&users3)
	fmt.Println(users3)

	//Limit:
	var users4 []User
	db.Limit(2).Find(&users4)
	fmt.Println(users4)
	//Offset:
	//注意:Offset中设置的偏移数字为第几条记录,从0开始,0、1、2、、、、
	//注意:Offset必须和Limit结合使用
	var users5 []User
	db.Offset(1).Limit(2).Find(&users5)
	fmt.Println(users5)
	//Scan
	type UserDemo struct { //你要扫描的结构体的字段的名字和User中的字段名字必须一致才可以扫描
		Name string
		Age  int
	}
	var userdemo UserDemo
	var user User
	db.Where("user_id=?", 1).Find(&user).Scan(&userdemo)
	fmt.Println(user)
	fmt.Println(userdemo)

	//Count:
	var users6 []User
	//定义一个变量接收计数的数量:
	var count int
	db.Find(&users6).Count(&count)
	fmt.Println(users6)
	fmt.Println(count)
	//Group:
	var users7 []User
	//定义一个新的结构体:
	type GroupData struct {
		Age   int
		Count int
	}
	var group_date []GroupData
	//Having:在分组以后进行过滤
	db.Debug().Select("age,count(*) as count").Group("age").Find(&users7).Having("age > 18").Scan(&group_date)
	fmt.Println(users7)
	fmt.Println(group_date)
}

【21】Join :左连接、右连接:
【22】LogMod:
Gorm内置的日志记录器,显示详细日志
PS :利用Debug只能逐条打印对应日志信息,但是设置LogMod(true)相当于设置了全局打印,所有执行的逻辑日志都会帮我们输出打印

package main

import (
	"fmt"
	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/mysql"
)

type User struct {
	UserId int `gorm:"primary_key;AUTO_INCREMENT"`
	Age    int
	Name   string
	IID    int
}

type UserInfo struct {
	InfoID  int `gorm:"primary_key;AUTO_INCREMENT"`
	Pic     string
	Address string
	Email   string
	User    User `gorm:"ForeignKey:IID;AssociationForeignKey:InfoID"` //关联关系
}

func main() {
	db, err := gorm.Open("mysql", "root:root@tcp(localhost:3306)/testgorm?charset=utf8&parseTime=True&loc=Local")
	if err != nil {
		panic(err)
	}
	defer db.Close()
	//开启打印日志:
	db.LogMode(true)
	db.DropTable(&User{})
	db.DropTable(&UserInfo{})
	db.CreateTable(&User{})
	db.CreateTable(&UserInfo{})
	//增加:Exec
	db.Exec("insert into users (age,name) values (?,?)", 28, "张无忌")
	db.Exec("insert into users (age,name) values (?,?)", 26, "赵敏")
	db.Exec("insert into users (age,name) values (?,?)", 25, "小昭")
	//Joins:
	//定义一个新的结构体用于Scan:
	type NewUserInfo struct {
		User_Id int
		Name    string
		I_Id    int
		Info_Id int
		Address string
	}
	var newUser []NewUserInfo
	var users []User
	db.Select("users.user_id,users.name,users.i_id,user_infos.info_id,user_infos.address").Joins("left join user_infos on users.i_id = user_infos.info_id").Find(&users).Scan(&newUser)
	fmt.Println(users)
	fmt.Println(newUser)
}

8、支持原生SQL

package main

import (
	"fmt"
	"github.com/jinzhu/gorm"
	_ "github.com/jinzhu/gorm/dialects/mysql"
)

type User struct {
	Name string
	Age  int
}

func main() {
	db, err := gorm.Open("mysql", "root:root@tcp(localhost:3306)/testgorm?charset=utf8&parseTime=True&loc=Local")
	if err != nil {
		panic(err)
	}
	defer db.Close()
	//开启打印日志:
	db.LogMode(true)
	db.CreateTable(&User{})

	//增加:Exec
	db.Exec("insert into users (age,name) values (?,?)", 18, "张无忌")
	//查询操作:Raw
	var users []User
	db.Raw("select * from users where age = ?", 18).Find(&users)
	fmt.Println(users)
	//删除、修改:Exec
	db.Exec("update users set name = ? where age = ?", "明明", 18)
	db.Exec("delete from users where age = ?", 18)
}

运行结果

(D:/GO_workspace_web/test_gorm/part04/main.go:23) 
[2023-08-19 21:48:51]  [40.40ms]  CREATE TABLE `users` (`name` varchar(255),`age` int )  
[0 rows affected or returned ] 

(D:/GO_workspace_web/test_gorm/part04/main.go:26)
[2023-08-19 21:48:51]  [5.56ms]  insert into users (age,name) values (18,'张无忌')
[1 rows affected or returned ]

(D:/GO_workspace_web/test_gorm/part04/main.go:29)
[2023-08-19 21:48:51]  [0.63ms]   select * from users where age = 18
[1 rows affected or returned ]
[{张无忌 18}]

(D:/GO_workspace_web/test_gorm/part04/main.go:32)
[2023-08-19 21:48:51]  [4.09ms]  update users set name = '明明' where age = 18
[1 rows affected or returned ]

(D:/GO_workspace_web/test_gorm/part04/main.go:33)
[2023-08-19 21:48:51]  [10.08ms]  delete from users where age = 18
[1 rows affected or returned ]

Process finished with the exit code 0

9、Gin整合GORM

人必须要成长!

如今一道为尊,万道相和,几乎很难破。最可怕的是苍穹!

你可能感兴趣的:(golang,开发语言,后端)