GORM
什么是ORM?
Object Relational Mapping 对象关系映射
官方网站:https://gorm.io/
Go语言中结构体与数据库的关系
数据表 == 结构体
数据行 == 结构体实例
数据表字段 == 结构体字段
安装GORM
go get -u github.com/jinzhu/gorm
导入GORM
导入对应的数据库驱动:
连接不同的数据库都需要导入对应数据的驱动程序,GORM
已经贴心的为我们包装了一些驱动程序,只需要按如下方式导入需要的数据库驱动即可:
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()
}
postgres
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()
}
sqlite
import (
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/sqlite"
)
func main() {
db, err := gorm.Open("sqlite3", "/tmp/gorm.db")
defer db.Close()
}
sqlserver
import (
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mssql"
)
func main() {
db, err := gorm.Open("mssql", "sqlserver://username:password@localhost:1433?database=dbname")
defer db.Close()
}
拓展学习:
在本地的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
#创建数据库
CREATE DATABASE db1;
模型定义
在使用ORM工具时,通常我们需要在代码中定义模型(Models)与数据库中的数据表进行映射,在GORM中模型(Models)通常是正常定义的结构体、基本的go类型或它们的指针。 同时也支持sql.Scanner
及driver.Valuer
接口(interfaces)。
gorm.Model
为了方便模型定义,GORM内置了一个gorm.Model
结构体。gorm.Model
是一个包含了ID
, CreatedAt
, UpdatedAt
, DeletedAt
四个字段的Golang结构体。
// gorm.Model 定义
type Model struct {
ID uint `gorm:"primary_key"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt *time.Time
}
你可以将它嵌入到你自己的模型中:
// 将 `ID`, `CreatedAt`, `UpdatedAt`, `DeletedAt`字段注入到`User`模型中
type User struct {
gorm.Model
Name string
}
当然也可以完全使用自己的模型:
type User struct {
ID uint
Name string
Email *string
Age uint8
Birthday *time.Time
MemberNumber sql.NullString
ActivatedAt sql.NullTime
CreatedAt time.Time
UpdatedAt time.Time
}
模型定义约定
//示例
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:"-"` // 忽略本字段
}
使用结构体声明模型时,标记(tags)是可选项。gorm支持以下标记:
Column 指定列名
Type 指定列数据类型
Size 指定列大小, 默认值255
PRIMARY_KEY 将列指定为主键
UNIQUE 将列指定为唯一
DEFAULT 指定列默认值
PRECISION 指定列精度
NOT NULL 将列指定为非 NULL
AUTO_INCREMENT 指定列是否为自增类型
INDEX 创建具有或不带名称的索引, 如果多个索引同名则创建复合索引
UNIQUE_INDEX 和 INDEX 类似,只不过创建的是唯一索引
EMBEDDED 将结构设置为嵌入
EMBEDDED_PREFIX 设置嵌入结构的前缀
- 忽略此字段
关联相关标记(tags):
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 是否自动完成预加载的相关操作
主键(Primary Key)
GORM 默认会使用名为ID的字段作为表的主键。
type User struct {
ID string // 名为`ID`的字段会默认作为表的主键
Name string
}
// 使用`AnimalID`作为主键
type Animal struct {
AnimalID int64 `gorm:"primary_key"`
Name string
Age int64
}
表名(Table Name)
表名默认就是结构体名称的复数,例如:
type User struct {} // 默认表名是 `users`
// 将 User 的表名设置为 `profiles`
func (User) TableName() string {
return "profiles"
}
func (u User) TableName() string {
if u.Role == "admin" {
return "admin_users"
} else {
return "users"
}
}
// 禁用默认表名的复数形式,如果置为 true,则 `User` 的默认表名是 `user`
db.SingularTable(true)
也可以通过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';
注意:结构体属性单词首字母要大写
列名(Column Name)
列名由字段名称进行下划线分割来生成:
type User struct {
ID uint // column name is `id`
Name string // column name is `name`
Birthday time.Time // column name is `birthday`
CreatedAt time.Time // column name is `created_at`
}
可以使用结构体tag指定列名:
type Animal struct {
AnimalId int64 `gorm:"column:beast_id"` // set column name to `beast_id`
Birthday time.Time `gorm:"column:day_of_the_beast"` // set column name to `day_of_the_beast`
Age int64 `gorm:"column:age_of_the_beast"` // set column name to `age_of_the_beast`
}
增加删除查找更新
package main
import (
"fmt"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/sqlite"
)
//定义用户结构体
type User struct {
//ID主键自增
ID int `gorm:"primary_key;AUTO_INCREMENT"`
Name string
Mail string
//设置默认值
Sex string `gorm:"default:'妖'"`
}
//继承gorm.Model
type TiemSub struct {
gorm.Model
}
//链接数据库
func connect() *gorm.DB {
db, err := gorm.Open("sqlite3", "gorm.db")
fmt.Println("connect ERR: ", err)
return db
}
//创建数据表
func createTab(db *gorm.DB) {
db.AutoMigrate(&User{}, &TiemSub{})
}
//插入记录
func add(db *gorm.DB) {
//创建对象插入
u1 := User{Name: "root", Mail: "root@root"}
db.Create(&u1)
u2 := User{
Name: "Mek",
Mail: "030399",
Sex: "男",
}
db.Create(&u2)
}
//查询并更新或删除
func update(db *gorm.DB) {
//查询
var u1 = new(User)
//条件查询
db.Find(&u1, "name=?", "Mek")
fmt.Println(u1.Mail, u1.Name)
//查询后更新更新
u1.Name = "ROOT"
db.Save(&u1)
fmt.Println("更新后!")
db.Find(&u1, "name=?", "Mek")
fmt.Println(u1.Mail, u1.Name)
//批量更新更新
db.Model(&User{}).Where("sex=?", "妖").Update("sex", "未知")
//根据主键单独删除
//删除主键为10的
db.Delete(&User{}, 10)
//批量删除
db.Delete(&User{}, "mail = ?", "")
db.Delete(&User{}, "mail LIKE ?", "%mmp%")
// DELETE from emails where email LIKE "%jinzhu%";
}
func main() {
db := connect()
createTab(db)
update(db)
}