gorm 初步研究实例

16次阅读

共计 6939 个字符,预计需要花费 18 分钟才能阅读完成。

表设计
CREATE TABLE `user` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT ‘ 自增 ID’,
`name` varchar(64) NOT NULL DEFAULT ” COMMENT ‘ 用户名 ’,
`age` int(11) NOT NULL DEFAULT ‘0’ COMMENT ‘ 年龄 ’,
`birthday` datetime NOT NULL DEFAULT ‘1000-01-01 00:00:00’ COMMENT ‘ 生日 ’,
`email` varchar(128) NOT NULL DEFAULT ” COMMENT ’email’,
`credit_card_id` int(11) NOT NULL DEFAULT ‘0’ COMMENT ‘ 信用卡 ID’,
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT ‘ 创建时间 ’,
`deleted_at` datetime NOT NULL DEFAULT ‘1000-01-01 00:00:00’ COMMENT ‘ 删除时间 ’,
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT ‘ 更新时间 ’,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT=’ 用户表 ’;

CREATE TABLE `credit_card` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT ‘ 自增 ID’,
`number` varchar(64) NOT NULL DEFAULT ” COMMENT ‘ 卡号 ’,
`user_id` int(11) NOT NULL DEFAULT ‘0’ COMMENT ‘ 用户 ID’,
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT ‘ 创建时间 ’,
`deleted_at` datetime NOT NULL DEFAULT ‘1000-01-01 00:00:00’ COMMENT ‘ 删除时间 ’,
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT ‘ 更新时间 ’,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT=’ 信用卡表 ’;

CREATE TABLE `phone` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT ‘ 自增 ID’,
`number` varchar(64) NOT NULL DEFAULT ” COMMENT ‘ 手机号 ’,
`user_id` int(11) NOT NULL DEFAULT ‘0’ COMMENT ‘ 用户 ID’,
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT ‘ 创建时间 ’,
`deleted_at` datetime NOT NULL DEFAULT ‘1000-01-01 00:00:00’ COMMENT ‘ 删除时间 ’,
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT ‘ 更新时间 ’,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT=’ 手机号表 ’;

CREATE TABLE `language` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT ‘ 自增 ID’,
`name` varchar(64) NOT NULL DEFAULT ” COMMENT ‘ 语言名称 ’,
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT ‘ 创建时间 ’,
`deleted_at` datetime NOT NULL DEFAULT ‘1000-01-01 00:00:00’ COMMENT ‘ 删除时间 ’,
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT ‘ 更新时间 ’,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT=’ 语言表 ’;

CREATE TABLE `user_language` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT ‘ 自增 ID’,
`user_id` int(11) NOT NULL DEFAULT ‘0’ COMMENT ‘ 用户 ID’,
`language_id` int(11) NOT NULL DEFAULT ‘0’ COMMENT ‘ 语言 ID’,
`created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT ‘ 创建时间 ’,
`deleted_at` datetime NOT NULL DEFAULT ‘1000-01-01 00:00:00’ COMMENT ‘ 删除时间 ’,
`updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT ‘ 更新时间 ’,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT=’ 用户语言关联表 ’;

模型
flame/gorm/model/user.go
package model

import (
“github.com/jinzhu/gorm”
“time”
)

type User struct {
gorm.Model
Name string
Age uint
Birthday *time.Time // 数据库字段值可以为 NULL 时得使用指针,否则可以不用指针
Email string

CreditCard *CreditCard // 避免循环嵌套,使用指针形式
//has one 模型
// 不填 foreignkey,默认就是【此字段 type】【CreditCard】+primarykey【ID】为【CreditCardID】
// 不填 association_foreignkey,默认就是【此字段 type】【User】的 primarykey【ID】,
// 即 `gorm:”foreignkey:CreditCardID;association_foreignkey:ID”`
CreditCardID uint
// 为 foreignkey,在本 struct 内,指向拥有哪个信用卡
//foreignkey【CreditCard】.【CreditCardID】———————>association_foreignkey【CreditCard】.【ID】

Phones []Phone `gorm:”foreignkey:UserID”`
//has many 模型 必须要配置 foreignkey
// 不填 association_foreignkey,默认就是【此 struct】【User】的 primarykey【ID】,
// 即 `gorm:”foreignkey:UserID;association_foreignkey:ID”`
//association_foreignkey【User】.【ID】———————>foreignkey【Phone】.【UserID】

Languages []Language `gorm:”many2many:user_language;”`
//many to many 模型 必须要配置 many2many
// 关联表为 user_language
// 不填 foreignkey,默认就是【此 struct】【User】的 primarykey【ID】
// 不填 association_foreignkey,默认就是【此字段 type】【Language】的 primarykey【ID】
// 不填 jointable_foreignkey,默认就是【此 struct】【User】+primarykey【ID】为【UserID】转换成【user_id】
// 不填 association_jointable_foreignkey,默认就是【此字段 type】【Language】+primarykey【ID】为【LanguageID】转换成【language_id】
//foreignkey【User】.【ID】———————>jointable_foreignkey【user_language】.【user_id】
//association_jointable_foreignkey【user_language】.【language_id】———————> 不填 association_foreignkey【Language】.【I】

// 多对多 存在循环时使用指针, 否则可以不用指针, 避免循环嵌套
}
flame/gorm/model/creditCard.go
package model

import (
“github.com/jinzhu/gorm”
)

type CreditCard struct {
gorm.Model
Number string

User *User // 避免循环嵌套,使用指针形式
//belong to 模型
// 不填 foreignkey,默认就是【此字段 type】【User】+primarykey【ID】为【UserID】
// 不填 association_foreignkey,默认就是此字段 type【User】的 primarykey【ID】,
// 即 `gorm:”foreignkey:UserID;association_foreignkey:ID”`
UserID int
// 为 foreignkey, 在本 struct 内,指向归属哪个 User
//foreignkey【CreditCard】.【UserID】———————>association_foreignkey【User】.【ID】

}
flame/gorm/model/phone.go
package model

import (
“github.com/jinzhu/gorm”
)

type Phone struct {
gorm.Model
Number string

User User
//belong to 模型
// 不填 foreignkey,默认就是此字段 type【User】+primarykey【ID】为【UserID】
// 不填 association_foreignkey,默认就是此字段 type【User】的 primarykey【ID】,
// 即 `gorm:”foreignkey:UserID;association_foreignkey:ID”`
UserID int
// 为 foreignkey, 在本 struct 内,指向归属哪个 User
//foreignkey【CreditCard】.【UserID】———————>association_foreignkey【User】.【ID】

}

flame/gorm/model/language.go
package model

import (
“github.com/jinzhu/gorm”
)

type Language struct {
gorm.Model
Name string
}
repository
flame/gorm/repository/User.go
package repository

import (
“errors”

“github.com/jinzhu/gorm”

“flame/gorm/model”
)

type UserRepository interface {
GetUserById(id int) (user model.User, err error)
}

func NewUserRepository(db *gorm.DB) UserRepository {
return &userDBRepository{db: db}
}

type userDBRepository struct {
db *gorm.DB
}

func(this *userDBRepository) GetUserById(id int)(user model.User, err error){
err = this.db.Where(“id = ?”, id).First(&user).Error
if err != nil {
return model.User{}, errors.New(“ 查询失败 ”)
}
return user, nil
}
dbinstance
flame/gorm/dbinstance/mysql.go
package dbinstance

import (
“fmt”
“os”
“log”
“sync”

“github.com/jinzhu/gorm”
_ “github.com/jinzhu/gorm/dialects/mysql”
)

var mysqlManager *MysqlManager
var mysqlOnce sync.Once
func GetMysqlInstance() *MysqlManager{
mysqlOnce.Do(func(){
mysqlManager=new(MysqlManager)
mysqlManager.init()
})

return mysqlManager
}

type MysqlManager struct {
DB *gorm.DB
ErrorMsg error
}

func (this *MysqlManager) init() (*gorm.DB,error) {
this.DB, this.ErrorMsg = gorm.Open(“mysql”, “<user>:<password>@tcp(<host>:<port>)/<db>?charset=utf8mb4&parseTime=True&loc=Local”)
fmt.Println(this.ErrorMsg)
if this.ErrorMsg != nil {
log.Fatal(this.ErrorMsg)
} else {
this.DB.SingularTable(true)// 表名为单数版
this.DB.LogMode(true) // 输出日志
this.DB.SetLogger(log.New(os.Stdout, “\r\n”, 0))// 输出到控制台

}

return this.DB,this.ErrorMsg
}

func (this *MysqlManager) Destroy(){
this.DB.Close()
}

main 测试
flame/gorm/main.go
package main

import (
“fmt”

“flame/gorm/dbinstance”
“flame/gorm/repository”
)

func main(){

mysqlManager:=dbinstance.GetMysqlInstance()
defer mysqlManager.Destroy()

db:=mysqlManager.DB

userDBRepository:=repository.NewUserRepository(db)
user,err:=userDBRepository.GetUserById(1)
fmt.Println(user)
fmt.Println(err)

}

运行得到输出
<nil>

sql/home/flame/go/src/flame/gorm/repository/User.go:243.526054msSELECT * FROM `user` WHERE `user`.`deleted_at` IS NULL AND ((id = ?))
ORDER BY `user`.`id` ASC LIMIT 1[1] 0
{{0 0001-01-01 00:00:00 +0000 UTC 0001-01-01 00:00:00 +0000 UTC <nil>} 0 <nil> <nil> 0 [] []}
查询失败
由于 gorm 判断带有 deleted_at 字段就会根据这个值是否 NULL 来判断是否删除,而我数据库字段设计是
`deleted_at` datetime NOT NULL DEFAULT ‘1000-01-01 00:00:00’ COMMENT ‘ 删除时间 ’,
有默认值,所以获取不到结果

正文完
 0