GORM学习之路

117 阅读6分钟

GORM学习之路

ORM

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

GORM

gorm是go语言的一个框架,Golang写的,开发人员友好的ORM库。 gorm中文文档

安装gorm

go get github.com/jinzhu/gorm

实例 增删改查

package main

import (
	"fmt"
	"gormtest/model"
	_ "gormtest/model"
	"gormtest/utils"
	_ "github.com/go-sql-driver/mysql"
)

func main() {
	db, err := utils.InitDB()
	if err != nil {
		fmt.Println("初始化失败", err)
	}
	// fmt.Println("初始化成功", db)
	//db.CreateTable(&model.User{})
	//删除表
	//db.DropTable(&model.User{})
	//通过字符串删除表
	//db.DropTable("users")
	//判断表是否存在
	//flag := db.HasTable("users")
	//fmt.Println("有没有", flag)
	//添加数据
	//db.Create(&model.User{Username: "lili", Password: "123456"})
	// //查询数据:第一个参数就是查询出来的数据的载体
	var user model.User
	//db.First(&user, "Username=?", "lili")
	//fmt.Println("有没有", user)
	//更新数据
	//db.Model(&user).Update("Username", "刘德华")
	//db.Model(&user).Update("Password", "1234567890")
	//db.First(&user, "Username=?", "刘德华")
	//fmt.Println("有没有", user)
	//删除数据
	//db.Delete(&user)
	db.First(&user, "Username=?", "刘德华")
	fmt.Println("有没有", user)
}

模型映射

  • 模型名和表名映射规则:
    • 如果模型名没有驼峰命名,那么表名就是:模型名小写+复数形式:如 User -> 表名Users。
    • 如果模型名有驼峰命名,那么表名就是:大写变小写并在前面加下划线,最后加上复数形式:如模型名UserInfo ->表名user_infos.
    • 如果模型名有连续的大写字母,那么表名就是:连续的大写字母变小写,驼峰变小写,驼峰前加下划线,字母变小写最后加上复数形式:如:DBUserInfo ->db_user_infos.
  • 自定义表名
type MyUser struct{
	Age int
	Name string
}
//如果自定义表名方法名必须为TableName(),在创建表时底层会自动调用
func (MyUser) TableName() string{
	return "test_my_user"
}

一对一关系(属于关系:关系和外键的指定在同一方)

package demostruct

// 一个用户对应一个用户信息
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:userRef;AssociationForeignKey:UserId"`
	//外键
	userRef int
}

一对一关系(包含关系:关系和外键的指定在不在同一方)

package demostruct

// 一个用户对应一个用户信息
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"`

}

1.一对一添加数据:

package main

import (
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	"gormtest/part1/demostruct"
	"gormtest/utils"
)

func main() {

	db, err := utils.InitDB()
	if err != nil {
		fmt.Println("初始化失败", err)
	}
	defer db.Close()
	db.CreateTable(&demostruct.User{})
	db.CreateTable(&demostruct.UserInfo{})

	//添加数据
	userinfo := demostruct.UserInfo{
		Pic:     "/upload/1.jpeg",
		Address: "上海虹口",
		Email:   "1231321@google.com",
		User: demostruct.User{
			Age:  19,
			Name: "旺旺",
		},
	}
	db.Create(&userinfo)
	
}
//结果

mysql> select * from user_infos;
+---------+----------------+--------------+--------------------+
| info_id | pic            | address      | email              |
+---------+----------------+--------------+--------------------+
|       1 | /upload/1.jpeg | 上海虹口     | 1231321@google.com |
|       2 | /upload/1.jpeg | 上海虹口     | 1231321@google.com |
+---------+----------------+--------------+--------------------+
2 rows in set (0.00 sec)

mysql> select * from users;
+---------+------+--------+------+
| user_id | age  | name   | i_id |
+---------+------+--------+------+
|       1 |   19 | 旺旺   |    1 |
|       2 |   19 | 旺旺   |    2 |
+---------+------+--------+------+
2 rows in set (0.00 sec)

2、查询 Association方式查询

//关联查询
	var userinfo demostruct.UserInfo
	//如果只是执行下边的查询,关联的user信息是查询不到的
	db.First(&userinfo, "info_id=?", 1)
	fmt.Println(userinfo)
	//结果
	{1 /upload/1.jpeg 上海虹口 1231321@google.com {0 0  0}}
	//如果想关联查询到user的信息,需要执行下边的查询
	//Model方法:参数,要查询的表数据,Association()参数,关联到的具体的模型:模型名,userinfo.User
	//find(),查询的数据要放在什么字段中&userinfo.User
	db.Model(&userinfo).Association("User").Find(&userinfo.User)
	fmt.Println(userinfo)
	//结果
	{1 /upload/1.jpeg 上海虹口 1231321@google.com {1 19 旺旺 1}}
db.Debug().First(&userinfo, "info_id=?", 1)
	fmt.Println(userinfo)
	//如果想关联查询到user的信息,需要执行下边的查询
	//Model方法:参数,要查询的表数据,Association()参数,关联到的具体的模型:模型名,userinfo.User
	//find(),查询的数据要放在什么字段中&userinfo.User
	db.Debug().Model(&userinfo).Association("User").Find(&userinfo.User)
	fmt.Println(userinfo)
通过Debug()可以查看运行的sql语句是什么样的。
[2024-01-16 16:27:30]  [0.88ms]  SELECT * FROM `user_infos`  WHERE (info_id=1) ORDER BY `user_infos`.`info_id` ASC LIMIT 1  
[1 rows affected or returned ] 
{1 /upload/1.jpeg 上海虹口 1231321@google.com {0 0  0}}
//将上面的sql查出来的userinfo表中的主键会作为下面sql的外键来查
[2024-01-16 16:27:30]  [0.69ms]  SELECT * FROM `users`  WHERE (`i_id` = 1)  
[1 rows affected or returned ] 
{1 /upload/1.jpeg 上海虹口 1231321@google.com {1 19 旺旺 1}}

Association方式查询需要先First查询再Association查询,步骤繁琐。

Preload方式查询:

package main

import (
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	"gormtest/part1/demostruct"
	"gormtest/utils"
)
func main() {
	db, err := utils.InitDB()
	if err != nil {
		fmt.Println("初始化失败", err)
	}

	defer db.Close()
	//preload方式查询
	var userinfo demostruct.UserInfo
	db.Debug().Preload("User").Find(&userinfo, "info_id=?", 1)
	fmt.Println(userinfo)
}
//sql语句
[2024-01-16 16:42:21]  [0.95ms]  SELECT * FROM `user_infos`  WHERE (info_id=1)  
[1 rows affected or returned ] 
[2024-01-16 16:42:21]  [0.87ms]  SELECT * FROM `users`  WHERE (`i_id` IN (1))  
[1 rows affected or returned ] 
{1 /upload/1.jpeg 上海虹口 1231321@google.com {1 19 旺旺 1}}

Related方式查询

package main

import (
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	_ "github.com/jinzhu/gorm"
	_ "gormtest/model"
	"gormtest/part1/demostruct"
	"gormtest/utils"
)

func main() {
	db, err := utils.InitDB()
	if err != nil {
		fmt.Println("初始化失败", err)
	}

	defer db.Close()
	//Related方式查询
	var userinfo demostruct.UserInfo
	db.First(&userinfo, "info_id=?", 1)
	fmt.Println(userinfo)
	var user demostruct.User
	//通过userinfo模型查出来的User字段的信息放入新的容器user中,单独查询user信息
	db.Model(&userinfo).Related(&user, "User")
	fmt.Println(user)
	fmt.Println(userinfo)
}
//查询结果
{1 /upload/1.jpeg 上海虹口 1231321@google.com {0 0  0}}
{1 19 旺旺 1}
{1 /upload/1.jpeg 上海虹口 1231321@google.com {0 0  0}}

3.更新

package main

import (
	"fmt"
	_ "github.com/go-sql-driver/mysql"
	_ "github.com/jinzhu/gorm"
	_ "gormtest/model"
	"gormtest/part1/demostruct"
	"gormtest/utils"
)

func main() {
	db, err := utils.InitDB()
	if err != nil {
		fmt.Println("初始化失败", err)
	}

	defer db.Close()
	//通过UserInfo表数据对User表中数据进行更新:
	var userinfo demostruct.UserInfo
	db.Debug().Preload("User").Find(&userinfo, "info_id=?", 1)
	fmt.Println(userinfo)
	//再更新:update的参数age可以使用结构体中字段Age,也可以使用数据库中字段age
	db.Model(&userinfo.User).Update("age", 18)
	fmt.Println(userinfo)
}

多对多

package demostruct
//一个作者有多篇文章
type Author struct {
	AID  int
	Name string
	Age  int
	Sex  string
	//关联关系
	Article []Article `gorm:"foreignKey:AuId;AssociationForeignKey:AID"`
}

type Article struct {
	ArId    int
	Title   string
	Content string
	Desc    string
	//设置外键
	AuId int
}

多对多

package demostruct

// 多对多
type Student struct {
	SId  int `gorm:"primary_key;AUTO_INCREMENT"`
	SNo  int
	Name string
	Sex  string
	Age  int
	//关联表
	Course []Course `gorm:"many2many:Studen_Course"`
}
type Course struct {
	Cid         int `gorm:"primary_key;AUTO_INCREMENT"`
	CName       string
	TeacherName string
	Room        string
}
日志Logrus

安装logrus: go get -u github.com/sirupsen/logrus

package logope

import (
	"encoding/json"
	"io/ioutil"
	"os"
)

// 日志结构体
type LogConfig struct {
	LogDir   string `json:"log_dir"`
	LogLevel string `json:log_level`
}

// 读取配置文件
func LoadLogConfig() *LogConfig {
	log_conf := LogConfig{}
	//打开文件
	file, err := os.Open("config/log_config.json")
	if err != nil {
		panic(err)
	}
	//释放资源
	defer file.Close()
	data, err1 := ioutil.ReadAll(file)
	if err1 != nil {
		panic(err1)
	}
	//将json字符串解码到对应的数据结构中
	//第一个参数:json字符串,第二个参数接收json解析的数据结构
	err2 := json.Unmarshal(data, &log_conf)
	if err2 != nil {
		panic(err2)
	}
	return &log_conf
}