GORM 사용자 정의 Gorm. Model 시간 스탬프 자동 추가
홈 페이지http://gorm.io) 기본 gorm. Model 모델 이 있 습 니 다. 정 의 는 다음 과 같 습 니 다.
package gorm
import "time"
// Model base model definition, including fields `ID`, `CreatedAt`, `UpdatedAt`, `DeletedAt`, which could be embedded in your models
// type User struct {
// gorm.Model
// }
type Model struct {
ID uint `gorm:"primary_key"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt *time.Time `sql:"index"`
}
네 개의 속성, ID, 생 성 시간, 업데이트 시간, 삭제 시간 을 포함 하 며, 데 이 터 를 조작 할 때 해당 시간 이 자동 으로 변경 되 며, 삭제 시 삭 제 를 소프트 삭제 로 변경 하고 삭제 시간 을 추가 합 니 다.
왜 홈 페이지 에 이미 있 는데 도 스스로 한 벌 써 야 합 니까?이 유 는 세 가지 가 있다.
1. 제 가 하 는 일 은 프로젝트 재 구성 입 니 다. 기 존의 데이터베이스 에 GUID 형식의 메 인 키 가 있 는데 이 모델 과 충돌 합 니 다. (왠 지 모 르 겠 지만 공식 적 으로 복합 메 인 키 를 지원 한다 고 명 확 히 밝 혔 지만 이렇게 하 는 것 을 권장 하지 않 습 니 다)
2. 세 개의 시간 필드 는 시간 을 저장 하고 원래 프로젝트 에 저 장 된 시간 스탬프 입 니 다.
3. 엄 살
재 작성 을 결정 한 이상 그 가 어떻게 작 동 하 는 지 먼저 알 아야 한다. 소스 코드 에서 DB 대상 을 찾 는 정 의 는 다음 과 같다.
db , value, product{}
type DB struct {
Value interface{}
Error error
RowsAffected int64
// single db
db SQLCommon // db.sql , query
blockGlobalUpdate bool
logMode int
logger logger
search *search // where, limit, group, db.clone() , search
values map[string]interface{}
// global db
parent *DB
callbacks *Callback // sql
dialect Dialect // sql.db
singularTable bool
}
// sql
type Scope struct {
Search *search //
Value interface{}
SQL string //sql
SQLVars []interface{}
db *DB //sql.db
instanceID string
primaryKeyField *Field
skipLeft bool
fields *[]*Field //
selectAttrs *[]string
}
// , create , creates
type Callback struct {
creates []*func(scope *Scope)
updates []*func(scope *Scope)
deletes []*func(scope *Scope)
queries []*func(scope *Scope)
rowQueries []*func(scope *Scope)
processors []*CallbackProcessor
}
코드 참조: https://blog.csdn.net/qq_17612199/article/details/79437795
(공식 소스 코드 에 주석 이 없습니다)
자, 이제 알 겠 습 니 다.
// Define callbacks for creating
func init() {
DefaultCallback.Create().Register("gorm:begin_transaction", beginTransactionCallback)
DefaultCallback.Create().Register("gorm:before_create", beforeCreateCallback)
DefaultCallback.Create().Register("gorm:save_before_associations", saveBeforeAssociationsCallback)
DefaultCallback.Create().Register("gorm:update_time_stamp", updateTimeStampForCreateCallback)
DefaultCallback.Create().Register("gorm:create", createCallback)
DefaultCallback.Create().Register("gorm:force_reload_after_create", forceReloadAfterCreateCallback)
DefaultCallback.Create().Register("gorm:save_after_associations", saveAfterAssociationsCallback)
DefaultCallback.Create().Register("gorm:after_create", afterCreateCallback)
DefaultCallback.Create().Register("gorm:commit_or_rollback_transaction", commitOrRollbackTransactionCallback)
}
'update 찾기time_stamp '대응 하 는 방법' updateTimeStampForCreateCallback '
// updateTimeStampForCreateCallback will set `CreatedAt`, `UpdatedAt` when creating
func updateTimeStampForCreateCallback(scope *Scope) {
if !scope.HasError() {
now := NowFunc()
if createdAtField, ok := scope.FieldByName("CreatedAt"); ok {
if createdAtField.IsBlank {
createdAtField.Set(now)
}
}
if updatedAtField, ok := scope.FieldByName("UpdatedAt"); ok {
if updatedAtField.IsBlank {
updatedAtField.Set(now)
}
}
}
}
// NowFunc returns current time, this function is exported in order to be able
// to give the flexibility to the developer to customize it according to their
// needs, e.g:
// gorm.NowFunc = func() time.Time {
// return time.Now().UTC()
// }
var NowFunc = func() time.Time {
return time.Now()
}
자, 이 단계 에 이 르 러 서 는 여러분 이 어떻게 다시 써 야 할 지 이미 알 고 있다 고 믿 습 니 다. 주의해 야 할 것 은 위의 Default Callback. Create () 가 사용 하 는 것 은 Register () 방법 입 니 다. Create () 의 정 의 는 다음 과 같 습 니 다.
// Register a new callback, refer `Callbacks.Create`
func (cp *CallbackProcessor) Register(callbackName string, callback func(scope *Scope)) {
if cp.kind == "row_query" {
if cp.before == "" && cp.after == "" && callbackName != "gorm:row_query" {
log.Printf("Registing RowQuery callback %v without specify order with Before(), After(), applying Before('gorm:row_query') by default for compatibility...
", callbackName)
cp.before = "gorm:row_query"
}
}
cp.name = callbackName
cp.processor = &callback
cp.parent.processors = append(cp.parent.processors, cp)
cp.parent.reorder()
}
이미 등록 을 했 으 니 다시 쓰 면 Register 를 사용 할 수 없습니다. 원본 코드 에서 원래 의 리 셋 을 바 꾸 는 방법 을 찾 았 습 니 다. 그 정 의 는 다음 과 같 습 니 다.
// Replace a registered callback with new callback
// db.Callback().Create().Replace("gorm:update_time_stamp_when_create", func(*Scope) {
// scope.SetColumn("Created", now)
// scope.SetColumn("Updated", now)
// })
func (cp *CallbackProcessor) Replace(callbackName string, callback func(scope *Scope)) {
log.Printf("[info] replacing callback `%v` from %v
", callbackName, fileWithLineNum())
cp.name = callbackName
cp.processor = &callback
cp.replace = true
cp.parent.processors = append(cp.parent.processors, cp)
cp.parent.reorder()
}
자, 파악 할 것 은 다 파악 하 였 으 니 지금부터 실제로 해 보 자.
프로젝트 에서 model 폴 더 는 맵 데이터베이스 모델 을 저장 하고 changemol. go 파일 을 새로 만 드 는 데 사 용 됩 니 다.
package model
type ChangeModel struct{
CreatedTime int32
UpdatedTime int32
DeletedTime int32
}
이벤트 기록 이 필요 한 모델 에 ChangeModel 을 도입 합 니 다.
package model
//User
type User struct{
ChangeModel
UserID string `gorm:"primary_key;size:36"`
Name string `gorm:"size:20"`
PassWord string `gorm:"size:40"`
}
자, 여기까지 사용자 정의 공공 필드 가 완료 되 었 습 니 다. 다음은 가장 중요 한 리 셋 과 주입 입 니 다.
데이터베이스 연결 파일 열기
package mysqltools
import (
"fmt"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
"log"
"sync"
"time"
)
type MysqlConnectiPool struct {
}
var instance *MysqlConnectiPool
var once sync.Once
var db *gorm.DB
var err_db error
func GetInstance() *MysqlConnectiPool {
once.Do(func() {
instance = &MysqlConnectiPool{}
})
return instance
}
/*
* @fuc ( mail() )
*/
func (m *MysqlConnectiPool) InitDataPool() (issucc bool) {
db, err_db = gorm.Open("mysql", "name:password@tcp(127.0.0.1:3306)/test?charset=utf8&parseTime=True&loc=Local")
fmt.Println(err_db)
if err_db != nil {
log.Fatal(err_db)
return false
}
db.DB().SetMaxIdleConns(10)
db.DB().SetMaxOpenConns(100)
db.DB().SetConnMaxLifetime(time.Hour)
db.Callback().Create().Replace("gorm:update_time_stamp",updateTimeStampForCreateCallback)
db.Callback().Update().Replace("gorm:update_time_stamp",updateTimeStampForUpdateCallback)
db.Callback().Delete().Replace("gorm:delete", deleteCallback)
return true
}
func (m *MysqlConnectiPool) GetMysqlDB() (db_con *gorm.DB) {
return db
}
// //
func updateTimeStampForCreateCallback(scope *gorm.Scope) {
if !scope.HasError() {
nowTime := time.Now().Unix()
if createTimeField, ok := scope.FieldByName("CreatedTime"); ok {
if createTimeField.IsBlank {
createTimeField.Set(nowTime)
}
}
if modifyTimeField, ok := scope.FieldByName("UpdatedTime"); ok {
if modifyTimeField.IsBlank {
modifyTimeField.Set(nowTime)
}
}
}
}
//
func updateTimeStampForUpdateCallback(scope *gorm.Scope) {
if _, ok := scope.Get("gorm:update_column"); !ok {
scope.SetColumn("UpdatedTime", time.Now().Unix())
}
}
//
func deleteCallback(scope *gorm.Scope) {
if !scope.HasError() {
var extraOption string
if str, ok := scope.Get("gorm:delete_option"); ok {
extraOption = fmt.Sprint(str)
}
deletedOnField, hasDeletedOnField := scope.FieldByName("DeletedTime")
if !scope.Search.Unscoped && hasDeletedOnField {
scope.Raw(fmt.Sprintf(
"UPDATE %v SET %v=%v%v%v",
scope.QuotedTableName(),
scope.Quote(deletedOnField.DBName),
scope.AddToVars(time.Now().Unix()),
addExtraSpaceIfExist(scope.CombinedConditionSql()),
addExtraSpaceIfExist(extraOption),
)).Exec()
} else {
scope.Raw(fmt.Sprintf(
"DELETE FROM %v%v%v",
scope.QuotedTableName(),
addExtraSpaceIfExist(scope.CombinedConditionSql()),
addExtraSpaceIfExist(extraOption),
)).Exec()
}
}
}
func addExtraSpaceIfExist(str string) string {
if str != "" {
return " " + str
}
return ""
}
세 개의 대응 하 는 리 셋 을 볼 수 있 습 니 다.
db.Callback().Create().Replace("gorm:update_time_stamp",updateTimeStampForCreateCallback)
db.Callback().Update().Replace("gorm:update_time_stamp",updateTimeStampForUpdateCallback)
db.Callback().Delete().Replace("gorm:delete", deleteCallback)
주의 하 다.
갈 고 리 는 만능 이 아니다. Raw () 를 사용 하여 원생 SQL 을 쓸 때 갈 고 리 는 효력 을 잃 고 대량 조작 은 갈 고 리 를 무효 로 할 수 있다. 또 다른 특수 한 방법 도 있 기 때문에 중요 한 데 이 터 는 절대 게 으 름 피 우지 말고 갈고리 로 조작 해 야 한다.
다음으로 전송:https://www.cnblogs.com/sgyBlog/p/10154424.html
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.