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
}