TOC
Когда мы используем golang для создания веб-приложения или других приложений, использующих базу данных,Обычно предпочитают использоватьgorm
Библиотека。Основная причина в том, чтоgorm
Библиотека Простота в эксплуатации,Простой и удобный в использовании.
В работе базы данных,Обычно приходится иметь дело со временем。иgorm
существоватьmodelОпределение структуры слоев,Также предоставленоtime.Time
тип。носуществоватьв реальном использовании,если мы не будем обращать внимание,Вы можете столкнуться с некоторыми странными проблемами.
1. Пустой тип времени записывается в базу данных и не может соответствовать формату времени типа datetime в mysql.
Error 1292 (22007): Incorrect datetime value: '0000-00-00' for column 'online_at' at row 1
существоватьдляTagповерхностьв определении,Видно, что мы определили три временных поля соответственно.:created_at
,updated_at
,online_at
。Обычно,существоватьданные Библиотекасерединаupdated_at
Поле будет установлено on update: CURRENT_TIMESTAMP
。То есть,Когда данные записываются или обновляются,данные Библиотекабудет обновляться автоматическиupdated_at
время в。так,Когда мы пишем код бизнес-логики,Нет необходимости обновлятьupdated_at
ценить。
но,created_at
и online_at
Два поля времени требуют, чтобы мы добавили или изменили их в бизнес-логике.
package model
import (
"time"
)
// Tag поверхность
type Tag struct {
Id uint `gorm:"column:id;type:int(11) unsigned;primary_key;AUTO_INCREMENT" json:"id"`
TagName string `gorm:"столбец:tag_name;тип:varchar(20);комментарий:ключевое слово;НЕ NULL" json:"tag_name"`
CreatedAt time.Time `gorm:"столбец:created_at;тип:datetime;комментарий:время создания" json:"created_at"`
UpdatedAt time.Time `gorm:"столбец:updated_at;тип:datetime;комментарий:время обновления" json:"updated_at"`
OnlineAt time.Time `gorm:"столбец:online_at;тип:datetime;комментарий:время онлайн" json:"online_at"`
}
// TableName -
func (m *Tag) TableName() string {
return "tag"
}
существоватьcontroller
слоистыйCreate()
Создание кода бизнес-логики,мы указалиCreatedAt
время создания,не указанOnlineAt
。 иисуществовать本身的业务逻辑середина,Также не следует указыватьOnlineAt
。
func (c *TagController) Create(tagName string) {
// Открыть транзакцию
tx := c.DB.Begin()
tagModel := &model.Tag{
TagName: tagName,
CreatedAt: time.Now(),
}
if err := tx.Create(tagModel).Error; err != nil {
// Создать неудачный откат
tx.Rollback()
fmt.Println(err)
}
// совершить транзакцию
if err := tx.Commit().Error; err != nil {
fmt.Println(err)
}
}
Когда мы выполняем приведенный выше код,Обнаружитьgorm
Сообщить об ошибке
2024/03/27 11:35:00 /Users/Kunkkawu/go/src/test/gorm_time/controller/tag.go:32 Error 1292 (22007): Incorrect datetime value: '0000-00-00' for column 'online_at' at row 1
[1.955ms] [rows:0] INSERT INTO `tag` (`tag_name`,`created_at`,`updated_at`,`online_at`) VALUES ('gorm_time','2024-03-27 11:35:00.306','2024-03-27 11:35:00.307','0000-00-00 00:00:00')
Error 1292 (22007): Incorrect datetime value: '0000-00-00' for column 'online_at' at row 1
sql: transaction has already been committed or rolled back
Это видно из сообщения об ошибке,online_at
Так как нет конкретной настройкиценить,иобнуляется'0000-00-00 00:00:00'
Сдержанный。
default:null
При определении тега modelкогда,Поскольку нет определенияdefault:null
,Поэтому, когда gorm обрабатывает SQL,Вместо этого автоматически будет использоваться нулевое значение.
// Tag поверхность
type Tag struct {
Id uint `gorm:"column:id;type:int(11) unsigned;primary_key;AUTO_INCREMENT" json:"id"`
TagName string `gorm:"столбец:tag_name;тип:varchar(20);комментарий:ключевое слово;НЕ NULL" json:"tag_name"`
CreatedAt time.Time `gorm:"столбец:created_at;тип:datetime;комментарий:время создания" json:"created_at"`
UpdatedAt time.Time `gorm:"столбец:updated_at;тип:datetime;комментарий:время обновления" json:"updated_at"`
OnlineAt time.Time `gorm:"столбец:online_at;тип:datetime;по умолчанию:null;комментарий:время онлайн" json:"online_at"`
}
При определении тега модель, если тип определен как *time.Time, Когда gorm обрабатывает SQL, нулевые значения будут склеены с null. Поэтому не будет Сообщить об ошибке。
// Tag поверхность
type Tag struct {
Id uint `gorm:"column:id;type:int(11) unsigned;primary_key;AUTO_INCREMENT" json:"id"`
TagName string `gorm:"столбец:tag_name;тип:varchar(20);комментарий:ключевое слово;НЕ NULL" json:"tag_name"`
CreatedAt *time.Time `gorm:"столбец:created_at;тип:datetime;комментарий:время создания" json:"created_at"`
UpdatedAt *time.Time `gorm:"столбец:updated_at;тип:datetime;комментарий:время обновления" json:"updated_at"`
OnlineAt *time.Time `gorm:"столбец:online_at;тип:datetime;комментарий:время онлайн" json:"online_at"`
}
Два метода, представленные выше,Оба могут быть решены из-за нулевого значения типа времени.,вызвало ошибки. Лично я рекомендую использовать теги gorm для установки значений по умолчанию. Таким образом, когда вам действительно нужно указать время,Просто нужноtime.Now()
Вот и все,инетt := time.Now()
а потом &t
Назначение.
Структура кода
model/tag.go
package model
import (
"time"
)
// Tag поверхность
type Tag struct {
Id uint `gorm:"column:id;type:int(11) unsigned;primary_key;AUTO_INCREMENT" json:"id"`
TagName string `gorm:"столбец:tag_name;тип:varchar(20);комментарий:ключевое слово;НЕ NULL" json:"tag_name"`
CreatedAt *time.Time `gorm:"столбец:created_at;тип:datetime;комментарий:время создания" json:"created_at"`
UpdatedAt *time.Time `gorm:"столбец:updated_at;тип:datetime;комментарий:время обновления" json:"updated_at"`
OnlineAt *time.Time `gorm:"столбец:online_at;тип:datetime;комментарий:время онлайн" json:"online_at"`
}
// TableName -
func (m *Tag) TableName() string {
return "tag"
}
controller/tag.go
package controller
import (
"fmt"
"test/utils/sqlmock/model"
"time"
"gorm.io/gorm"
)
type TagController struct {
DB *gorm.DB
}
func (c *TagController) Create(tagName string) {
// Открыть транзакцию
tx := c.DB.Begin()
t := time.Now()
tagModel := &model.Tag{
TagName: tagName,
CreatedAt: &t,
}
if err := tx.Create(tagModel).Error; err != nil {
// Создать неудачный откат
tx.Rollback()
fmt.Println(err)
}
// совершить транзакцию
if err := tx.Commit().Error; err != nil {
fmt.Println(err)
}
}
func (c *TagController) GetInfo(tagName string) {
tagModel := &model.Tag{}
if err := c.DB.Where("tag_name = ?", tagName).First(tagModel).Error; err != nil {
fmt.Println(err)
}
fmt.Println(tagModel.Id)
fmt.Println(tagModel.TagName)
fmt.Println(tagModel.CreatedAt.Format(time.DateTime))
fmt.Println(tagModel.UpdatedAt.Format(time.DateTime))
}
main.go
package main
import (
"test/gorm_time/controller"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
func main() {
db := initDB()
tagCtrl := controller.TagController{
DB: db,
}
tagCtrl.Create("gorm_time")
tagCtrl.GetInfo("gorm_time")
}
func initDB() *gorm.DB {
dsn := "root:@tcp(127.0.0.1:3306)/test?charset=utf8&parseTime=true&loc=Asia%2FShanghai"
db, err := gorm.Open(mysql.Open(dsn))
if err != nil {
panic(err)
}
return db
}