Skip to content

编写数据模型

baseModel:

go
package models

import (
	"gorm.io/plugin/soft_delete"
	"time"
)

type BaseModel struct {
	CreatedAt  time.Time             `json:"create_at" gorm:"autoCreateTime"`
	ModifiedAt time.Time             `json:"modified_at" gorm:"autoUpdateTime"`
	DeletedAt  soft_delete.DeletedAt `json:"deleted_at" `
}
package models

import (
	"gorm.io/plugin/soft_delete"
	"time"
)

type BaseModel struct {
	CreatedAt  time.Time             `json:"create_at" gorm:"autoCreateTime"`
	ModifiedAt time.Time             `json:"modified_at" gorm:"autoUpdateTime"`
	DeletedAt  soft_delete.DeletedAt `json:"deleted_at" `
}

问答“题目”模型:

go
import (
	"fmt"
	"gorm.io/datatypes"
)

type Option struct {
	Key   string `json:"key"`
	Value string `json:"value"`
}

type Question struct {
	BaseModel
	ID    uint   `json:"id"`
	Title string `json:"title" gorm:"column:title"`
	// 问题选项: 存储JSON字符串, 例如 {A:'1',B:'2', C: '3'} 题目展示的时候,按key的顺序进行排序
	Options datatypes.JSON `json:"options"`
	// 问题类型:1单选题 2多选题 3思考题(无答案选项)
	Type string `json:"type" gorm:"column:type"`
	// 问题答案:
	Answer string `json:"answer" gorm:"column:answer"`
	// 问题解释
	Explanation string `json:"explanation" gorm:"column:explanation"`
}

func (Question) TableName() string {
	return "q_question"
}
import (
	"fmt"
	"gorm.io/datatypes"
)

type Option struct {
	Key   string `json:"key"`
	Value string `json:"value"`
}

type Question struct {
	BaseModel
	ID    uint   `json:"id"`
	Title string `json:"title" gorm:"column:title"`
	// 问题选项: 存储JSON字符串, 例如 {A:'1',B:'2', C: '3'} 题目展示的时候,按key的顺序进行排序
	Options datatypes.JSON `json:"options"`
	// 问题类型:1单选题 2多选题 3思考题(无答案选项)
	Type string `json:"type" gorm:"column:type"`
	// 问题答案:
	Answer string `json:"answer" gorm:"column:answer"`
	// 问题解释
	Explanation string `json:"explanation" gorm:"column:explanation"`
}

func (Question) TableName() string {
	return "q_question"
}

数据库的初始化:

go
package models

import (
	"QuizStar/pkg/logging"
	"fmt"
	"gorm.io/driver/sqlite"
	"gorm.io/gorm"
	"log"
)

var db *gorm.DB

func SetUp() {
	var err error
	db, err = gorm.Open(sqlite.Open("quiz.db"), &gorm.Config{})
	fmt.Println(db)
	if err != nil {
		panic("failed to connect database")
	}
	// db = db.Table("q_question")
	// 迁移 schema
	err = db.AutoMigrate(&Question{})
	if err != nil {
		logging.Error(err)
		log.Fatal(err)
	}
}
package models

import (
	"QuizStar/pkg/logging"
	"fmt"
	"gorm.io/driver/sqlite"
	"gorm.io/gorm"
	"log"
)

var db *gorm.DB

func SetUp() {
	var err error
	db, err = gorm.Open(sqlite.Open("quiz.db"), &gorm.Config{})
	fmt.Println(db)
	if err != nil {
		panic("failed to connect database")
	}
	// db = db.Table("q_question")
	// 迁移 schema
	err = db.AutoMigrate(&Question{})
	if err != nil {
		logging.Error(err)
		log.Fatal(err)
	}
}

模型类的封装方法:

go
func CreateQuestion(question *Question) error {
	fmt.Println(db)
	return db.Create(question).Error
}

func UpdateQuestionAllField(question *Question) error {
	return db.Save(question).Error
}

func UpdateQuestion(question *Question) error {
	// 仅更新非零值字段
	return db.Model(&question).Updates(question).Error
}

func DeleteQuestion(id int) error {
	return db.Delete(&Question{}, id).Error
}

func GetQuestionByID(id int) (*Question, error) {
	var question Question
	err := db.First(&question, id).Error
	if err != nil {
		return nil, err
	}
	return &question, nil
}
func CreateQuestion(question *Question) error {
	fmt.Println(db)
	return db.Create(question).Error
}

func UpdateQuestionAllField(question *Question) error {
	return db.Save(question).Error
}

func UpdateQuestion(question *Question) error {
	// 仅更新非零值字段
	return db.Model(&question).Updates(question).Error
}

func DeleteQuestion(id int) error {
	return db.Delete(&Question{}, id).Error
}

func GetQuestionByID(id int) (*Question, error) {
	var question Question
	err := db.First(&question, id).Error
	if err != nil {
		return nil, err
	}
	return &question, nil
}

编写测试用例:

go
package models

import (
	"fmt"
	"gorm.io/datatypes"
	"testing"
)

func TestCreateQuestion(t *testing.T) {
	SetUp()
	fmt.Println(db)
	// 创建
	question := &Question{
		Title:       "Sample Question",
		Options:     datatypes.JSON("{\"1\", \"Option 1\"}, {\"2\", \"Option 2\"}"),
		Type:        "Multiple Choice",
		Answer:      "1",
		Explanation: "This is the explanation for the correct answer",
	}
	err := CreateQuestion(question)
	if err != nil {
		t.Errorf("Failed to create question: %v", err)
	}
}

func TestUpdateQuestion(t *testing.T) {
	SetUp()
	question := &Question{
		ID:    2,
		Title: "Sample Question2",
	}
	err := UpdateQuestion(question)
	if err != nil {
		t.Errorf("Failed to update question: %v", err)
	}
	q, err := GetQuestionByID(2)
	if err != nil {
		t.Errorf("Failed to get question: %v", err)
	}
	fmt.Printf("%v", q)
}

func TestDeleteQuestion(t *testing.T) {
	SetUp()
	err := DeleteQuestion(1)
	if err != nil {
		t.Errorf("Failed to delete question: %v", err)
	}
}
package models

import (
	"fmt"
	"gorm.io/datatypes"
	"testing"
)

func TestCreateQuestion(t *testing.T) {
	SetUp()
	fmt.Println(db)
	// 创建
	question := &Question{
		Title:       "Sample Question",
		Options:     datatypes.JSON("{\"1\", \"Option 1\"}, {\"2\", \"Option 2\"}"),
		Type:        "Multiple Choice",
		Answer:      "1",
		Explanation: "This is the explanation for the correct answer",
	}
	err := CreateQuestion(question)
	if err != nil {
		t.Errorf("Failed to create question: %v", err)
	}
}

func TestUpdateQuestion(t *testing.T) {
	SetUp()
	question := &Question{
		ID:    2,
		Title: "Sample Question2",
	}
	err := UpdateQuestion(question)
	if err != nil {
		t.Errorf("Failed to update question: %v", err)
	}
	q, err := GetQuestionByID(2)
	if err != nil {
		t.Errorf("Failed to get question: %v", err)
	}
	fmt.Printf("%v", q)
}

func TestDeleteQuestion(t *testing.T) {
	SetUp()
	err := DeleteQuestion(1)
	if err != nil {
		t.Errorf("Failed to delete question: %v", err)
	}
}

低级错误引起search not found的问题

测试过程中发现,发现如果是多次连续查询出现record not found的问题:第二次查询会携带第一次查询的查询条件(例如 id = 1 and id = 2)
经过排查,发现与 db = db.Table("q_question") 语句有关。

解决方法1

  1. 删除Setup中的db = db.Table("q_question")
  2. 并在具体查询的时候指定下Table("q_question")
go
func GetQuestionByID(id uint) (*Question, error) {
	var question Question
	err := db.Table("q_question").Where("id = ?", id).First(&question).Error
	if err != nil {
		return nil, err
	}
	return &question, nil
}
func GetQuestionByID(id uint) (*Question, error) {
	var question Question
	err := db.Table("q_question").Where("id = ?", id).First(&question).Error
	if err != nil {
		return nil, err
	}
	return &question, nil
}

解决方法2

  1. 删除Setup中的db = db.Table("q_question")
  2. 数据模型制定对应TableName
go
func (Question) TableName() string {
	return "q_question"
}

func GetQuestionByID(id uint) (*Question, error) {
	var question Question
	err := db.First(&question, id).Error
	if err != nil {
		return nil, err
	}
	return &question, nil
}
func (Question) TableName() string {
	return "q_question"
}

func GetQuestionByID(id uint) (*Question, error) {
	var question Question
	err := db.First(&question, id).Error
	if err != nil {
		return nil, err
	}
	return &question, nil
}

相关参考:
浅谈 GORM 默认值处理