go语言 gin框架学习系列(四):gorm操作MySQL数据库

38 阅读3分钟

1.初始化

1.1 连接数据库

func main() {
    // 1.创建路由
    r := gin.Default()

    err := db.InitMysqlDB() // 初始化数据库
    if err != nil {
       fmt.Printf("数据库连接失败,err:%v\n", err)
       return
    }

新建文件db/mysql.go

package db

import (
    "fmt"
    "gorm.io/driver/mysql"
    "gorm.io/gorm"
)

type Stu struct {
    Id   int
    Name string
    Age  int
    Sex  string
}

// TableName 指定表名
func (Stu) TableName() string {
    return "student"
}

var db *gorm.DB
var err error

// 初始化mysql 客户端
func InitMysqlDB() (err error) {
    //初始化数据库
    // DSN:Data Source Name
    // dsn,字符串中,包含了连接mysql所需要的一些信息。
    // 比如用户名user,密码password,mysql的服务ip,port,还有数据库名称sql_test

    // 这段代码首先通过 sql.Open() 函数创建了一个 mysql 数据库连接。
    // 其中第一个参数是驱动名称,
    // 第二个参数是连接字符串,格式为 用户名:密码@协议(地址:端口)/数据库名称。
    dsn := "root:123456@tcp(127.0.0.1:3306)/jassue_gin?charset=utf8mb4&parseTime=True"
    db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
    if err != nil { // 检测连接是否成功
       return err
    }

    db.AutoMigrate(&Stu{}) // 自动迁移表

    user := Stu{Name: "linjing", Age: 18, Sex: "女"} // 创建一条数据
    result := db.Create(&user)                      // 通过数据的指针来创建
    fmt.Println(result)

    return nil
}

数据库连接成功,并插入一条数据。

image.png

1.2 数据库方法分离(控制器调用model方法)

新建model/user.go 文件,将操作数据库的方法移入

package model

import (
    "fmt"
)

type Stu struct {
    Name string
    Age  int
    Sex  string
}

// TableName 指定表名
func (Stu) TableName() string {
    return "student"
}

func Create(data *Stu) int {
    result := Db.Create(data)
    if result.Error != nil {
       return 400
    }
    return 200
}

新建model/core.go 文件

package model

import "gorm.io/gorm"

var Db *gorm.DB

优化controller/userController.go 方法

package api

import (
    "fmt"
    "github.com/gin-gonic/gin"
    "jassue-gin/model"
    "strconv"
)

type UserController struct {
    // 继承 BaseController
    BaseController
}

func (con UserController) Add(c *gin.Context) {
    // 获取参数
    name := c.PostForm("name")
    age, _ := strconv.Atoi(c.PostForm("age"))
    sex := c.PostForm("sex")

    data := model.Stu{Name: name, Age: age, Sex: sex}  

    fmt.Println(data)
    model.Create(&data) // post请求插入一条数据
}
...

优化db/mysql.go 代码

package db

import (
    "fmt"
    "gorm.io/driver/mysql"
    "gorm.io/gorm"
    "jassue-gin/model"
)

var db *gorm.DB
var err error

var (
    stu model.Stu
)

// 初始化mysql 客户端
func InitMysqlDB() (err error) {
    username := "root"
    password := "123456"
    host := "127.0.0.1"
    port := 3306
    Dbname := "jassue_gin"
    timeout := "10s"
    dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local&timeout=%s", username, password, host, port, Dbname, timeout)
    fmt.Println(dsn) // root:123456@tcp(127.0.0.1:3306)/jassue_gin?charset=utf8mb4&parseTime=True&loc=Local&timeout=10s

 
    db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
    if err != nil { // 检测连接是否成功
       return err
    }

    db.AutoMigrate(&stu) // 自动迁移表

    model.Db = db // 重要!!!
    return nil
}

遇到问题:当分离了model方法后,启动项目报错。

image.png 原因:在mysql.go中初始化了db,又在user.go重新声明了db,导致db为空指针。 model/user.go

package model

import (
    "fmt"
    "gorm.io/gorm"   // 错误原因
)

var db *gorm.DB  // 错误原因

type Stu struct {
    Name string
    Age  int
    Sex  string
}

// TableName 指定表名
func (Stu) TableName() string {
    return "student"
}

func Create(data *Stu) int {

    fmt.Println("----", data)
    result := db.Create(data)
    if result.Error != nil {
       return 400
    }
    return 200
}

解决方法一:在mysql.go中添加model.Db = db,并在model/core.go中引入

import "gorm.io/gorm"

var Db *gorm.DB

就可以在model包中的文件中直接使用Db。

解决方式二: 在mysql.go中添加model.SetDb(MysqlDb),并在model/core.go中

package model

import "gorm.io/gorm"

var Db *gorm.DB
var DbTransaction *gorm.DB


func SetDb(database *gorm.DB) {
    Db = database
    DbTransaction = database
}

以上修改完后,修改model/user.go

package model

import "fmt" 

type Stu struct {
    Name string
    Age  int
    Sex  string
}

// TableName 指定表名
func (Stu) TableName() string {
    return "student"
}

func Create(data *Stu) int {

    fmt.Println("----", data)
    result := Db.Create(data)
    if result.Error != nil {
       return 400
    }
    return 200
}

1.3 数据库方法分离(加入service层,controller->service->model)

controller/userController.go

func (con UserController) Add(c *gin.Context) {
    // 获取参数
    name := c.PostForm("name")
    age, _ := strconv.Atoi(c.PostForm("age"))
    sex := c.PostForm("sex")
    
    data := model.Stu{Name: name, Age: age, Sex: sex}

    fmt.Println(data)
    service.CreateUser(&data) // 调用service方法
}

新建service/service.go

package service

import (
    "fmt"
    "jassue-gin/model"
)

func CreateUser(data *model.Stu) int {
    fmt.Println("service", data)
    return model.Create(data)
}

2.gorm模型定义

定义Stu结构体

type Stu struct { 
    Name string 
    Age int 
    Sex string 
}

优化为:

type Stu struct {
    Id   int    `json:"id" gorm:"column:id;type:int;primarykey;auto_increment"`
    Name string `json:"name" gorm:"column:name;type:varchar(16);unique_index;not null;default:name;"`
    Age  int    `json:"age" gorm:"column:age;type:tinyint;not null;default:18;"`
    Sex  int    `json:"sex" gorm:"column:sex;type:tinyint;not null;default:0;"`
}

image.png

gorm mysql字段标签

image.png