GORM数据库连接和模型定义 | 青训营

110 阅读5分钟

GORM

GORM 指南 | GORM - The fantastic ORM library for Golang, aims to be developer friendly.

介绍

ORM = Object(对象:程序中的对象/实例,例如Go中的结构体实例)+ Relational(关系:关系数据库,例如MySQL)+ Mapping(映射)

//demo
type UserInfo struct{
    ID uint 
    Name string 
    Gender string 
    Hobby string
}
func main() {
    u1 := UserInfo{1, "七米", "男", "篮球"}
    //将u1数据存入数据库
    orm.Create(&u1) //ORM语句
}

ORM优缺点:

优点缺点
提高开发效率牺牲执行性能
牺牲灵活性
弱化SQL能力

安装

go get -u github.com/jinzhu/gorm

连接数据库

GORM 目前支持 MySQL、SQLServer、PostgreSQL、SQLite。

import _ "github.com/jinzhu/gorm/dialects/mysql"
// import _ "github.com/jinzhu/gorm/dialects/postgres"
// import _ "github.com/jinzhu/gorm/dialects/sqlite"
// import _ "github.com/jinzhu/gorm/dialects/mssql"

连接MySQL

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

func main() {
  	db, err := gorm.Open("mysql", "user:password@(localhost)/dbname?charset=utf8mb4&parseTime=True&loc=Local")
  	defer db.Close()
}

连接PostgreSQL

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

func main() {
  	db, err := gorm.Open("postgres", "host=myhost port=myport user=gorm dbname=gorm password=mypassword")
  	defer db.Close()
}

连接Sqlite3

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

func main() {
  	db, err := gorm.Open("sqlite3", "/tmp/gorm.db")
  	defer db.Close()
}

Gorm的基本使用

Docker快速创建MySQL实例

在本地的13306端口运行一个名为mysql8019,root用户名密码为root1234的MySQL容器环境:

docker run --name mysql8019 -p 13306:3306 -e MYSQL_ROOT_PASSWORD=root1234 -d mysql:8.0.19

在另外启动一个MySQL Client连接上面的MySQL环境,密码为上一步指定的密码root1234:

docker run -it --network host --rm mysql mysql -h127.0.0.1 -P13306 --default-character-set=utf8mb4 -uroot -p

安装MySQL并创建库(我的方案)

Gorm Demo

什么是DSN:github.com/go-sql-driv…

// 学会使用go mod tidy命令
package main

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

type UserInfo struct {
	ID     uint
	Name   string
	Gender string
	Hobby  string
}

func main() {
	db, err := gorm.Open("mysql", "root:123456@(127.0.0.1:13306)/test?charset=utf8mb4&parseTime=True&loc=Local")
    //另一种连接方式
    gorm.Open(
        mysql.Open("user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"), //dsn
        &gorm.Config{}
    )

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

	db.AutoMigrate(&UserInfo{})

	//新增
	u1 := UserInfo{1, "阿一", "女", "跑步"}
	u2 := UserInfo{2, "阿仪", "女", "游泳"}
	db.Create(&u1)
	db.Create(&u2)

	////查询
	//var u UserInfo
	//db.First(&u)
	//fmt.Printf("u:%#v\n", u)
	//
	////更新
	//db.Model(&u).Update("hobby", "散步")
	//
	////删除
	//db.Delete(&u)
}

GORM Model定义

在使用ORM工具时,通常我们需要在代码中定义模型(Models)与数据库中的数据表进行映射,在GORM中模型(Models)通常是正常定义的结构体、基本的go类型或它们的指针。 同时也支持**sql.Scannerdriver.Valuer接口(interfaces)**。

GORM的内置gorm.Model结构体

// gorm.Model 定义
type Model struct {
  	ID        uint `gorm:"primary_key"`
  	CreatedAt time.Time
  	UpdatedAt time.Time
  	DeletedAt *time.Time
}

可以将其嵌入自定义的模型中,也可以不使用

模型定义Demo

type User struct {
  	gorm.Model								
  	Name         string			
  	Age          sql.NullInt64
  	Birthday     *time.Time
  	Email        string  `gorm:"type:varchar(100);unique_index"`
  	Role         string  `gorm:"size:255"` // 设置字段大小为255
  	MemberNumber *string `gorm:"unique;not null"` // 设置会员号(member number)唯一并且不为空
  	Num          int     `gorm:"AUTO_INCREMENT"` // 设置 num 为自增类型
  	Address      string  `gorm:"index:addr"` // 给address字段创建名为addr的索引
  	IgnoreMe     int     `gorm:"-"` // 忽略本字段
}

结构体标记

结构体标记(Tag)描述
Column指定列名
Type指定列数据类型
Size指定列大小, 默认值255
PRIMARY_KEY将列指定为主键
UNIQUE将列指定为唯一
DEFAULT指定列默认值
PRECISION指定列精度
NOT NULL将列指定为非 NULL
AUTO_INCREMENT指定列是否为自增类型
INDEX创建具有或不带名称的索引, 如果多个索引同名则创建复合索引
UNIQUE_INDEXINDEX 类似,只不过创建的是唯一索引
EMBEDDED将结构设置为嵌入
EMBEDDED_PREFIX设置嵌入结构的前缀
-忽略此字段

结构体标记(Tag)描述
MANY2MANY指定连接表
FOREIGNKEY设置外键
ASSOCIATION_FOREIGNKEY设置关联外键
POLYMORPHIC指定多态类型
POLYMORPHIC_VALUE指定多态值
JOINTABLE_FOREIGNKEY指定连接表的外键
ASSOCIATION_JOINTABLE_FOREIGNKEY指定连接表的关联外键
SAVE_ASSOCIATIONS是否自动完成 save 的相关操作
ASSOCIATION_AUTOUPDATE是否自动完成 update 的相关操作
ASSOCIATION_AUTOCREATE是否自动完成 create 的相关操作
ASSOCIATION_SAVE_REFERENCE是否自动完成引用的 save 的相关操作
PRELOAD是否自动完成预加载的相关操作

主键、表名和列名修改默认

主键

GORM默认使用名为ID的字段作为表的主键,如果没有ID字段则自动增加ID字段,也可以手动设置主键字段。

type User struct {
  ID   string // 名为`ID`的字段会默认作为表的主键
  Name string
}

// 使用`AnimalID`作为主键
type Animal struct {
  AnimalID int64 `gorm:"primary_key"`
  Name     string
  Age      int64
}

表名

表名默认是结构体名称的复数,如果按照驼峰命名法,表名则由用下划线连接的小写单词组成。可以自定义名称,可以禁用复数形式,还支持更改默认表名规则。

// 将 User 结构体映射的表重命名为 `profiles`
func (User) TableName() string {
  	return "profiles"
}

func (u User) TableName() string {
      if u.Role == "admin" {
        return "admin_users"
      } else {
        return "users"
      }
}

// 禁用默认表名的复数形式,如果置为 true,则不使用复数
db.SingularTable(true)

// 给默认表名加前缀
gorm.DefaultTableNameHandler = func (db *gorm.DB, defaultTableName string) string  {
  return "prefix_" + defaultTableName;
}

可以使用db.AutoMigrate(&UserInfo{})创建表,也可以使用CreateTable创建表,用Table()指定表名:

// 使用User结构体创建名为`deleted_users`的表
db.Table("deleted_users").CreateTable(&User{})

var deleted_users []User
db.Table("deleted_users").Find(&deleted_users)
//// SELECT * FROM deleted_users;

db.Table("deleted_users").Where("name = ?", "jinzhu").Delete()
//// DELETE FROM deleted_users WHERE name = 'jinzhu';

列名

列名默认由字段名称用下划线分割成的小写单词组成,可以使用结构体tag指定列名。

type Animal struct {
      AnimalId    int64     `gorm:"column:beast_id"`         
      Birthday    time.Time `gorm:"column:day_of_the_beast"` 
      Age         int64     `gorm:"column:age_of_the_beast"`
}

时间戳

CreatedAt

如果模型有 CreatedAt字段,该字段的值将会是初次创建记录的时间。

db.Create(&user) // `CreatedAt`将会是当前时间

// 可以使用`Update`方法来改变`CreateAt`的值
db.Model(&user).Update("CreatedAt", time.Now())

UpdatedAt

如果模型有UpdatedAt字段,该字段的值将会是每次更新记录的时间。

db.Save(&user) // `UpdatedAt`将会是当前时间

db.Model(&user).Update("name", "jinzhu") // `UpdatedAt`将会是当前时间

DeletedAt

如果模型有DeletedAt字段,调用Delete删除该记录时,将会设置DeletedAt字段为当前时间,而不是直接将记录从数据库中删除。