Maison >développement back-end >Golang >Golang GORM implémente archived_at similaire à la suppression logicielle

Golang GORM implémente archived_at similaire à la suppression logicielle

WBOY
WBOYavant
2024-02-05 22:33:12489parcourir

Golang GORM 实现类似于软删除的archived_at

Contenu des questions

J'utilise GORM V1. J'ai une exigence, nous voulons ajouter un deleted_atarchived_at 列。实体可以存档和取消存档,默认情况下我们希望使用 archived_at de type GORM pour NULL pour interroger les enregistrements.

Mon idée actuelle est d'utiliser les rappels GORM pour enregistrer les rappels

  1. Enregistrez le rappel avant gorm:query callback.
  2. Vérifiez si le schéma/modèle nécessite le champ archived_at.
  3. Si le champ existe, veuillez ajouter les conditions nécessaires.

Cela semble bien, mais comment copier efficacement l'équivalent du Unscoped() de l'archive.

  • Quelle est la manière idiomatique d'obtenir des enregistrements archivés ? Comment indiquer si une colonne archived_at doit être ajoutée au rappel nécessaire ?
  • Je me retrouve également dans une situation où je souhaite simplement obtenir des enregistrements archivés (où archived_at N'EST PAS NULL).

EDIT - Mon cas d'utilisation consiste à utiliser à la fois les champs deleted_at et deleted_atarchived_at, plutôt que d'utiliser un champ à la place de l'autre. Je souhaite conserver la possibilité de suppression logicielle tout en ajoutant la possibilité d'archiver des entités. L'utilisateur peut simplement être archivé puis éventuellement supprimé (soft delete).


Réponse correcte


Inviter des commentaires. C'est ce à quoi je pense en ce moment.

callback.go

package db

import (
    "fmt"
    "reflect"

    "gorm.io/gorm"
)

const (
    gormsettingkeyunscopearchive = "unscope_archive"
    structfieldnamearchivedat    = "archivedat"
)

// archivedquerycallback - conditionally adds "where archived_at is null" if the model being queried has the following
// 1. struct field represented by structfieldnamearchivedat
// 2. gorm instance setting gormsettingkeyunscopearchive, see unscopearchive
func archivedquerycallback(db *gorm.db) {
    // check if model is a pointer and has an indirect struct type
    if db.statement.model != nil &&
        reflect.typeof(db.statement.model).kind() == reflect.ptr &&
        reflect.indirect(reflect.valueof(db.statement.model)).kind() == reflect.struct {
        stmt := &gorm.statement{db: db}
        parseerr := stmt.parse(db.statement.model)
        if parseerr != nil {
            panic(parseerr)
        }

        if _, archivedatexists := stmt.schema.fieldsbyname[structfieldnamearchivedat]; archivedatexists {
            v, ok := db.instanceget(gormsettingkeyunscopearchive)
            if ok {
                if v == true {
                    return
                }
            }

            db.where(fmt.sprintf("%s is null", stmt.schema.fieldsbyname[structfieldnamearchivedat].dbname))
        }
    }
}

scope.go

// unscopearchive - sets a true value for the key gormsettingkeyunscopearchive
func unscopearchive(db *gorm.db) *gorm.db {
    db = db.instanceset(gormsettingkeyunscopearchive, true)

    return db
}

main.go

   type User {
       ID           string         `gorm:"primary_key" json:"id" valid:"uuidv4, optional"`
    CreatedAt    time.Time      `valid:"-" json:"created_at"`
    UpdatedAt    time.Time      `valid:"-" json:"-"`
    DeletedAt    gorm.DeletedAt `sql:"index" valid:"-" json:"-"`
    ArchivedAt   time.Time
   }

   var user []User
   ctx := context.Background()
   dbClient := InitializeGORM() //helper 
   _ := dbClient.WithContext(ctx).Find(&user).Error // SELECT * FROM users WHERE deleted_at IS NULL AND archived_at IS NULL;

   _ := dbClient.WithContext(ctx).Scopes(UnscopeArchive).Find(&user).Error // SELECT * FROM users WHERE deleted_at IS NULL;

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer