diff --git a/mayfly_go_web/src/views/ops/db/SyncTaskLog.vue b/mayfly_go_web/src/views/ops/db/SyncTaskLog.vue index e35984aa..ebb931a3 100644 --- a/mayfly_go_web/src/views/ops/db/SyncTaskLog.vue +++ b/mayfly_go_web/src/views/ops/db/SyncTaskLog.vue @@ -4,13 +4,9 @@ - @@ -21,6 +17,7 @@ import { reactive, Ref, ref, toRefs, watch } from 'vue'; import { dbApi } from '@/views/ops/db/api'; import PageTable from '@/components/pagetable/PageTable.vue'; import { TableColumn } from '@/components/pagetable'; +import { DbDataSyncLogStatusEnum } from './enums'; const props = defineProps({ taskId: { @@ -36,7 +33,7 @@ const dialogVisible = defineModel('visible', { default: false }); const columns = ref([ // 状态:1.成功 -1.失败 - TableColumn.new('status', '状态').alignCenter().isSlot(), + TableColumn.new('status', '状态').alignCenter().typeTag(DbDataSyncLogStatusEnum), TableColumn.new('createTime', '时间').alignCenter().isTime(), TableColumn.new('errText', '日志'), TableColumn.new('dataSqlFull', 'SQL').alignCenter(), diff --git a/mayfly_go_web/src/views/ops/db/enums.ts b/mayfly_go_web/src/views/ops/db/enums.ts index 4e77b289..0f63c988 100644 --- a/mayfly_go_web/src/views/ops/db/enums.ts +++ b/mayfly_go_web/src/views/ops/db/enums.ts @@ -14,6 +14,12 @@ export const DbDataSyncRecentStateEnum = { Fail: EnumValue.of(-1, '失败').setTagType('danger'), }; +export const DbDataSyncLogStatusEnum = { + Success: EnumValue.of(1, '成功').setTagType('success'), + Wait: EnumValue.of(2, '同步中').setTagType('primary'), + Fail: EnumValue.of(-1, '失败').setTagType('danger'), +}; + export const DbDataSyncRunningStateEnum = { Success: EnumValue.of(1, '运行中').setTagType('success'), Wait: EnumValue.of(2, '待运行').setTagType('primary'), diff --git a/server/internal/db/api/db.go b/server/internal/db/api/db.go index 95f69a83..9b2509b9 100644 --- a/server/internal/db/api/db.go +++ b/server/internal/db/api/db.go @@ -62,7 +62,7 @@ func (d *Db) Save(rc *req.Ctx) { rc.ReqParam = form - biz.ErrIsNil(d.DbApp.Save(rc.MetaCtx, db, form.TagId...)) + biz.ErrIsNil(d.DbApp.SaveDb(rc.MetaCtx, db, form.TagId...)) } func (d *Db) DeleteDb(rc *req.Ctx) { diff --git a/server/internal/db/api/db_data_sync.go b/server/internal/db/api/db_data_sync.go index 80219287..8e178b74 100644 --- a/server/internal/db/api/db_data_sync.go +++ b/server/internal/db/api/db_data_sync.go @@ -66,9 +66,7 @@ func (d *DataSyncTask) DeleteTask(rc *req.Ctx) { for _, v := range ids { value, err := strconv.Atoi(v) biz.ErrIsNilAppendErr(err, "string类型转换为int异常: %s") - id := uint64(value) - _ = d.DataSyncTaskApp.Delete(rc.MetaCtx, id) - _ = d.DataSyncTaskApp.RemoveCronJobById(id) + biz.ErrIsNil(d.DataSyncTaskApp.Delete(rc.MetaCtx, uint64(value))) } } @@ -76,10 +74,13 @@ func (d *DataSyncTask) ChangeStatus(rc *req.Ctx) { form := &form.DataSyncTaskStatusForm{} task := ginx.BindJsonAndCopyTo[*entity.DataSyncTask](rc.GinCtx, form, new(entity.DataSyncTask)) _ = d.DataSyncTaskApp.UpdateById(context.Background(), task) + if task.Status == entity.DataSyncTaskStatusEnable { - _ = d.DataSyncTaskApp.AddCronJobById(task.Id) + task, err := d.DataSyncTaskApp.GetById(new(entity.DataSyncTask), task.Id) + biz.ErrIsNil(err, "该任务不存在") + d.DataSyncTaskApp.AddCronJob(task) } else { - _ = d.DataSyncTaskApp.RemoveCronJobById(task.Id) + d.DataSyncTaskApp.RemoveCronJobById(task.Id) } // 记录请求日志 rc.ReqParam = form diff --git a/server/internal/db/application/db.go b/server/internal/db/application/db.go index cd4074bd..53995309 100644 --- a/server/internal/db/application/db.go +++ b/server/internal/db/application/db.go @@ -24,7 +24,7 @@ type Db interface { Count(condition *entity.DbQuery) int64 - Save(ctx context.Context, entity *entity.Db, tagIds ...uint64) error + SaveDb(ctx context.Context, entity *entity.Db, tagIds ...uint64) error // 删除数据库信息 Delete(ctx context.Context, id uint64) error @@ -66,7 +66,7 @@ func (d *dbAppImpl) Count(condition *entity.DbQuery) int64 { return d.GetRepo().Count(condition) } -func (d *dbAppImpl) Save(ctx context.Context, dbEntity *entity.Db, tagIds ...uint64) error { +func (d *dbAppImpl) SaveDb(ctx context.Context, dbEntity *entity.Db, tagIds ...uint64) error { // 查找是否存在 oldDb := &entity.Db{Name: dbEntity.Name, InstanceId: dbEntity.InstanceId} err := d.GetBy(oldDb) diff --git a/server/internal/db/application/db_data_sync.go b/server/internal/db/application/db_data_sync.go index 5fa5345f..a53606a4 100644 --- a/server/internal/db/application/db_data_sync.go +++ b/server/internal/db/application/db_data_sync.go @@ -31,13 +31,7 @@ type DataSyncTask interface { AddCronJob(taskEntity *entity.DataSyncTask) - AddCronJobById(id uint64) error - - RemoveCronJob(taskEntity *entity.DataSyncTask) - - RemoveCronJobById(id uint64) error - - RemoveCronJobByKey(taskKey string) + RemoveCronJobById(taskId uint64) RunCronJob(id uint64) error @@ -62,15 +56,26 @@ func (app *dataSyncAppImpl) GetPageList(condition *entity.DataSyncTaskQuery, pag } func (app *dataSyncAppImpl) Save(ctx context.Context, taskEntity *entity.DataSyncTask) error { - app.AddCronJob(taskEntity) + var err error if taskEntity.Id == 0 { - return app.Insert(ctx, taskEntity) + err = app.Insert(ctx, taskEntity) + } else { + err = app.UpdateById(ctx, taskEntity) } - return app.UpdateById(ctx, taskEntity) + if err != nil { + return err + } + + app.AddCronJob(taskEntity) + return nil } func (app *dataSyncAppImpl) Delete(ctx context.Context, id uint64) error { - return app.DeleteById(ctx, id) + if err := app.DeleteById(ctx, id); err != nil { + return err + } + app.RemoveCronJobById(id) + return nil } func (app *dataSyncAppImpl) AddCronJob(taskEntity *entity.DataSyncTask) { @@ -88,31 +93,10 @@ func (app *dataSyncAppImpl) AddCronJob(taskEntity *entity.DataSyncTask) { } } -func (app *dataSyncAppImpl) AddCronJobById(id uint64) error { - task, err := app.GetById(new(entity.DataSyncTask), id) - if err != nil { - return err - } - app.AddCronJob(task) - return nil -} - -func (app *dataSyncAppImpl) RemoveCronJob(taskEntity *entity.DataSyncTask) { - app.RemoveCronJobByKey(taskEntity.TaskKey) -} - -func (app *dataSyncAppImpl) RemoveCronJobById(id uint64) error { - task, err := app.GetById(new(entity.DataSyncTask), id) - if err != nil { - return err - } - app.RemoveCronJob(task) - return nil -} - -func (app *dataSyncAppImpl) RemoveCronJobByKey(taskKey string) { - if taskKey != "" { - scheduler.RemoveByKey(taskKey) +func (app *dataSyncAppImpl) RemoveCronJobById(taskId uint64) { + task, err := app.GetById(new(entity.DataSyncTask), taskId) + if err == nil { + scheduler.RemoveByKey(task.TaskKey) } } @@ -148,30 +132,40 @@ func (app *dataSyncAppImpl) RunCronJob(id uint64) error { // 组装查询sql sql := fmt.Sprintf("select * from (%s) t where 1 = 1 %s %s", task.DataSql, updSql, orderSql) - err = app.doDataSync(sql, task) + log, err := app.doDataSync(sql, task) if err != nil { - app.endRunning(task, entity.DataSyncTaskStateFail, fmt.Sprintf("执行失败: %s", err.Error()), sql, 0) + log.ErrText = fmt.Sprintf("执行失败: %s", err.Error()) + log.Status = entity.DataSyncTaskStateFail + app.endRunning(task, log) } }() return nil } -func (app *dataSyncAppImpl) doDataSync(sql string, task *entity.DataSyncTask) error { +func (app *dataSyncAppImpl) doDataSync(sql string, task *entity.DataSyncTask) (*entity.DataSyncLog, error) { + now := time.Now() + syncLog := &entity.DataSyncLog{ + TaskId: task.Id, + CreateTime: &now, + DataSqlFull: sql, + Status: entity.DataSyncTaskStateRunning, + } + // 获取源数据库连接 srcConn, err := GetDbApp().GetDbConn(uint64(task.SrcDbId), task.SrcDbName) if err != nil { - return errorx.NewBiz("连接源数据库失败: %s", err.Error()) + return syncLog, errorx.NewBiz("连接源数据库失败: %s", err.Error()) } // 获取目标数据库连接 targetConn, err := GetDbApp().GetDbConn(uint64(task.TargetDbId), task.TargetDbName) if err != nil { - return errorx.NewBiz("连接目标数据库失败: %s", err.Error()) + return syncLog, errorx.NewBiz("连接目标数据库失败: %s", err.Error()) } targetDbTx, err := targetConn.Begin() if err != nil { - return errorx.NewBiz("开启目标数据库事务失败: %s", err.Error()) + return syncLog, errorx.NewBiz("开启目标数据库事务失败: %s", err.Error()) } defer func() { if r := recover(); r != nil { @@ -188,7 +182,7 @@ func (app *dataSyncAppImpl) doDataSync(sql string, task *entity.DataSyncTask) er var fieldMap []map[string]string err = json.Unmarshal([]byte(task.FieldMap), &fieldMap) if err != nil { - return errorx.NewBiz("解析字段映射json出错: %s", err.Error()) + return syncLog, errorx.NewBiz("解析字段映射json出错: %s", err.Error()) } var updFieldType dbm.DataType @@ -218,6 +212,12 @@ func (app *dataSyncAppImpl) doDataSync(sql string, task *entity.DataSyncTask) er if err := app.srcData2TargetDb(result, fieldMap, updFieldType, task, srcDialect, targetDialect, targetDbTx); err != nil { return err } + + // 记录当前已同步的数据量 + syncLog.ErrText = fmt.Sprintf("本次任务执行中,已同步:%d条", total) + syncLog.ResNum = total + app.saveLog(syncLog) + result = result[:0] } @@ -226,25 +226,29 @@ func (app *dataSyncAppImpl) doDataSync(sql string, task *entity.DataSyncTask) er if err != nil { targetDbTx.Rollback() - return err + return syncLog, err } // 处理剩余的数据 if len(result) > 0 { if err := app.srcData2TargetDb(result, fieldMap, updFieldType, task, srcDialect, targetDialect, targetDbTx); err != nil { targetDbTx.Rollback() - return err + return syncLog, err } } if err := targetDbTx.Commit(); err != nil { - return errorx.NewBiz("数据同步-目标数据库事务提交失败: %s", err.Error()) + return syncLog, errorx.NewBiz("数据同步-目标数据库事务提交失败: %s", err.Error()) } logx.Infof("同步任务:[%s],执行完毕,保存记录成功:[%d]条", task.TaskName, total) // 保存执行成功日志 - app.endRunning(task, entity.DataSyncTaskStateSuccess, fmt.Sprintf("本次任务执行成功,新数据:%d 条", total), "", total) - return nil + syncLog.ErrText = fmt.Sprintf("本次任务执行成功,新数据:%d 条", total) + syncLog.Status = entity.DataSyncTaskStateSuccess + syncLog.ResNum = total + app.endRunning(task, syncLog) + + return syncLog, nil } func (app *dataSyncAppImpl) srcData2TargetDb(srcRes []map[string]any, fieldMap []map[string]string, updFieldType dbm.DataType, task *entity.DataSyncTask, srcDialect dbm.DbDialect, targetDialect dbm.DbDialect, targetDbTx *sql.Tx) error { @@ -304,9 +308,10 @@ func (app *dataSyncAppImpl) srcData2TargetDb(srcRes []map[string]any, fieldMap [ return nil } -func (app *dataSyncAppImpl) endRunning(taskEntity *entity.DataSyncTask, state int8, msg string, sql string, resNum int) { - logx.Info(msg) +func (app *dataSyncAppImpl) endRunning(taskEntity *entity.DataSyncTask, log *entity.DataSyncLog) { + logx.Info(log.ErrText) + state := log.Status task := new(entity.DataSyncTask) task.Id = taskEntity.Id task.RecentState = state @@ -321,19 +326,11 @@ func (app *dataSyncAppImpl) endRunning(taskEntity *entity.DataSyncTask, state in //} _ = app.UpdateById(context.Background(), task) // 保存执行日志 - app.saveLog(taskEntity.Id, state, msg, sql, resNum) + app.saveLog(log) } -func (app *dataSyncAppImpl) saveLog(taskId uint64, state int8, msg string, sql string, resNum int) { - now := time.Now() - _ = app.dataSyncLogRepo.Insert(context.Background(), &entity.DataSyncLog{ - TaskId: taskId, - CreateTime: &now, - DataSqlFull: sql, - ResNum: resNum, - ErrText: msg, - Status: state, - }) +func (app *dataSyncAppImpl) saveLog(log *entity.DataSyncLog) { + app.dataSyncLogRepo.Save(context.Background(), log) } func (app *dataSyncAppImpl) InitCronJob() { diff --git a/server/internal/db/dbm/conn.go b/server/internal/db/dbm/conn.go index 0b95cb41..ee3b7333 100644 --- a/server/internal/db/dbm/conn.go +++ b/server/internal/db/dbm/conn.go @@ -92,11 +92,7 @@ func (d *DbConn) TxExec(tx *sql.Tx, execSql string, args ...any) (int64, error) // 执行 update, insert, delete,建表等sql // 返回影响条数和错误 func (d *DbConn) ExecContext(ctx context.Context, execSql string, args ...any) (int64, error) { - res, err := d.db.ExecContext(ctx, execSql, args...) - if err != nil { - return 0, wrapSqlError(err) - } - return res.RowsAffected() + return d.TxExecContext(ctx, nil, execSql, args...) } // 事务执行 update, insert, delete,建表等sql,若tx == nil,则不适用事务 diff --git a/server/internal/db/domain/entity/db_data_sync.go b/server/internal/db/domain/entity/db_data_sync.go index 3324f731..586bcdfd 100644 --- a/server/internal/db/domain/entity/db_data_sync.go +++ b/server/internal/db/domain/entity/db_data_sync.go @@ -56,6 +56,7 @@ const ( DataSyncTaskStatusDisable int8 = -1 // 禁用状态 DataSyncTaskStateSuccess int8 = 1 // 执行成功状态 + DataSyncTaskStateRunning int8 = 2 // 执行成功状态 DataSyncTaskStateFail int8 = -1 // 执行失败状态 DataSyncTaskRunStateRunning int8 = 1 // 运行中状态 diff --git a/server/internal/machine/api/machine.go b/server/internal/machine/api/machine.go index f53721e6..74cc1860 100644 --- a/server/internal/machine/api/machine.go +++ b/server/internal/machine/api/machine.go @@ -80,7 +80,7 @@ func (m *Machine) SaveMachine(rc *req.Ctx) { machineForm.Password = "******" rc.ReqParam = machineForm - biz.ErrIsNil(m.MachineApp.Save(rc.MetaCtx, me, machineForm.TagId...)) + biz.ErrIsNil(m.MachineApp.SaveMachine(rc.MetaCtx, me, machineForm.TagId...)) } func (m *Machine) TestConn(rc *req.Ctx) { diff --git a/server/internal/machine/api/machine_cronjob.go b/server/internal/machine/api/machine_cronjob.go index a9080c13..a77cefbc 100644 --- a/server/internal/machine/api/machine_cronjob.go +++ b/server/internal/machine/api/machine_cronjob.go @@ -36,7 +36,7 @@ func (m *MachineCronJob) Save(rc *req.Ctx) { mcj := ginx.BindJsonAndCopyTo[*entity.MachineCronJob](rc.GinCtx, jobForm, new(entity.MachineCronJob)) rc.ReqParam = jobForm - cronJobId, err := m.MachineCronJobApp.Save(rc.MetaCtx, mcj) + cronJobId, err := m.MachineCronJobApp.SaveMachineCronJob(rc.MetaCtx, mcj) biz.ErrIsNil(err) // 关联机器 diff --git a/server/internal/machine/application/machine.go b/server/internal/machine/application/machine.go index e1c7b716..739d20f2 100644 --- a/server/internal/machine/application/machine.go +++ b/server/internal/machine/application/machine.go @@ -23,7 +23,7 @@ import ( type Machine interface { base.App[*entity.Machine] - Save(ctx context.Context, m *entity.Machine, tagIds ...uint64) error + SaveMachine(ctx context.Context, m *entity.Machine, tagIds ...uint64) error // 测试机器连接 TestConn(me *entity.Machine) error @@ -74,7 +74,7 @@ func (m *machineAppImpl) GetMachineList(condition *entity.MachineQuery, pagePara return m.GetRepo().GetMachineList(condition, pageParam, toEntity, orderBy...) } -func (m *machineAppImpl) Save(ctx context.Context, me *entity.Machine, tagIds ...uint64) error { +func (m *machineAppImpl) SaveMachine(ctx context.Context, me *entity.Machine, tagIds ...uint64) error { oldMachine := &entity.Machine{ Ip: me.Ip, Port: me.Port, diff --git a/server/internal/machine/application/machine_cronjob.go b/server/internal/machine/application/machine_cronjob.go index 50f03af6..d13109dc 100644 --- a/server/internal/machine/application/machine_cronjob.go +++ b/server/internal/machine/application/machine_cronjob.go @@ -26,7 +26,7 @@ type MachineCronJob interface { // 获取分页执行结果列表 GetExecPageList(condition *entity.MachineCronJobExec, pageParam *model.PageParam, toEntity any, orderBy ...string) (*model.PageResult[any], error) - Save(ctx context.Context, entity *entity.MachineCronJob) (uint64, error) + SaveMachineCronJob(ctx context.Context, entity *entity.MachineCronJob) (uint64, error) Delete(ctx context.Context, id uint64) @@ -84,7 +84,7 @@ func (m *machineCropJobAppImpl) GetExecPageList(condition *entity.MachineCronJob } // 保存机器任务信息 -func (m *machineCropJobAppImpl) Save(ctx context.Context, mcj *entity.MachineCronJob) (uint64, error) { +func (m *machineCropJobAppImpl) SaveMachineCronJob(ctx context.Context, mcj *entity.MachineCronJob) (uint64, error) { // 更新操作 if mcj.Id != 0 { m.UpdateById(ctx, mcj) diff --git a/server/internal/mongo/api/mongo.go b/server/internal/mongo/api/mongo.go index da0ccc21..e8311725 100644 --- a/server/internal/mongo/api/mongo.go +++ b/server/internal/mongo/api/mongo.go @@ -60,7 +60,7 @@ func (m *Mongo) Save(rc *req.Ctx) { }(form.Uri) rc.ReqParam = form - biz.ErrIsNil(m.MongoApp.Save(rc.MetaCtx, mongo, form.TagId...)) + biz.ErrIsNil(m.MongoApp.SaveMongo(rc.MetaCtx, mongo, form.TagId...)) } func (m *Mongo) DeleteMongo(rc *req.Ctx) { diff --git a/server/internal/mongo/application/mongo.go b/server/internal/mongo/application/mongo.go index f4367537..8c934185 100644 --- a/server/internal/mongo/application/mongo.go +++ b/server/internal/mongo/application/mongo.go @@ -21,7 +21,7 @@ type Mongo interface { TestConn(entity *entity.Mongo) error - Save(ctx context.Context, entity *entity.Mongo, tagIds ...uint64) error + SaveMongo(ctx context.Context, entity *entity.Mongo, tagIds ...uint64) error // 删除数据库信息 Delete(ctx context.Context, id uint64) error @@ -76,7 +76,7 @@ func (d *mongoAppImpl) TestConn(me *entity.Mongo) error { return nil } -func (d *mongoAppImpl) Save(ctx context.Context, m *entity.Mongo, tagIds ...uint64) error { +func (d *mongoAppImpl) SaveMongo(ctx context.Context, m *entity.Mongo, tagIds ...uint64) error { oldMongo := &entity.Mongo{Name: m.Name, SshTunnelMachineId: m.SshTunnelMachineId} err := d.GetBy(oldMongo) diff --git a/server/internal/redis/api/redis.go b/server/internal/redis/api/redis.go index 84295670..fbd381a0 100644 --- a/server/internal/redis/api/redis.go +++ b/server/internal/redis/api/redis.go @@ -69,7 +69,7 @@ func (r *Redis) Save(rc *req.Ctx) { form.Password = "****" rc.ReqParam = form - biz.ErrIsNil(r.RedisApp.Save(rc.MetaCtx, redis, form.TagId...)) + biz.ErrIsNil(r.RedisApp.SaveRedis(rc.MetaCtx, redis, form.TagId...)) } // 获取redis实例密码,由于数据库是加密存储,故提供该接口展示原文密码 diff --git a/server/internal/redis/application/redis.go b/server/internal/redis/application/redis.go index c1403a35..3334e501 100644 --- a/server/internal/redis/application/redis.go +++ b/server/internal/redis/application/redis.go @@ -24,7 +24,7 @@ type Redis interface { // 测试连接 TestConn(re *entity.Redis) error - Save(ctx context.Context, re *entity.Redis, tagIds ...uint64) error + SaveRedis(ctx context.Context, re *entity.Redis, tagIds ...uint64) error // 删除数据库信息 Delete(ctx context.Context, id uint64) error @@ -68,7 +68,7 @@ func (r *redisAppImpl) TestConn(re *entity.Redis) error { return nil } -func (r *redisAppImpl) Save(ctx context.Context, re *entity.Redis, tagIds ...uint64) error { +func (r *redisAppImpl) SaveRedis(ctx context.Context, re *entity.Redis, tagIds ...uint64) error { // 查找是否存在该库 oldRedis := &entity.Redis{ Host: re.Host, diff --git a/server/pkg/base/app.go b/server/pkg/base/app.go index cca4e607..b4305976 100644 --- a/server/pkg/base/app.go +++ b/server/pkg/base/app.go @@ -40,6 +40,13 @@ type App[T model.ModelI] interface { // 根据实体条件,更新参数udpateFields指定字段 Updates(ctx context.Context, cond any, udpateFields map[string]any) error + // 保存实体,实体IsCreate返回true则新增,否则更新 + Save(ctx context.Context, e T) error + + // 保存实体,实体IsCreate返回true则新增,否则更新。 + // 使用指定gorm db执行,主要用于事务执行 + SaveWithDb(ctx context.Context, db *gorm.DB, e T) error + // 根据实体条件删除实体 DeleteByCond(ctx context.Context, cond any) error @@ -115,6 +122,17 @@ func (ai *AppImpl[T, R]) Updates(ctx context.Context, cond any, udpateFields map return ai.GetRepo().Updates(cond, udpateFields) } +// 保存实体,实体IsCreate返回true则新增,否则更新 +func (ai *AppImpl[T, R]) Save(ctx context.Context, e T) error { + return ai.GetRepo().Save(ctx, e) +} + +// 保存实体,实体IsCreate返回true则新增,否则更新。 +// 使用指定gorm db执行,主要用于事务执行 +func (ai *AppImpl[T, R]) SaveWithDb(ctx context.Context, db *gorm.DB, e T) error { + return ai.GetRepo().SaveWithDb(ctx, db, e) +} + // 根据实体主键删除实体 (单纯删除实体,不做其他业务逻辑处理) func (ai *AppImpl[T, R]) DeleteById(ctx context.Context, id uint64) error { return ai.GetRepo().DeleteById(ctx, id) diff --git a/server/pkg/base/repo.go b/server/pkg/base/repo.go index 81c956f5..3e839269 100644 --- a/server/pkg/base/repo.go +++ b/server/pkg/base/repo.go @@ -33,6 +33,13 @@ type Repo[T model.ModelI] interface { // 使用指定gorm db执行,主要用于事务执行 UpdateByIdWithDb(ctx context.Context, db *gorm.DB, e T, columns ...string) error + // 保存实体,实体IsCreate返回true则新增,否则更新 + Save(ctx context.Context, e T) error + + // 保存实体,实体IsCreate返回true则新增,否则更新。 + // 使用指定gorm db执行,主要用于事务执行 + SaveWithDb(ctx context.Context, db *gorm.DB, e T) error + // 根据实体主键删除实体 DeleteById(ctx context.Context, id uint64) error @@ -121,11 +128,25 @@ func (br *RepoImpl[T]) Updates(cond any, udpateFields map[string]any) error { return gormx.Updates(br.GetModel(), cond, udpateFields) } +func (br *RepoImpl[T]) Save(ctx context.Context, e T) error { + if e.IsCreate() { + return br.Insert(ctx, e) + } + return br.UpdateById(ctx, e) +} + +func (br *RepoImpl[T]) SaveWithDb(ctx context.Context, db *gorm.DB, e T) error { + if e.IsCreate() { + return br.InsertWithDb(ctx, db, e) + } + return br.UpdateByIdWithDb(ctx, db, e) +} + func (br *RepoImpl[T]) DeleteById(ctx context.Context, id uint64) error { if db := contextx.GetDb(ctx); db != nil { return br.DeleteByIdWithDb(ctx, db, id) } - return gormx.DeleteById(br.getModel(), id) + return gormx.DeleteById(br.GetModel(), id) } func (br *RepoImpl[T]) DeleteByIdWithDb(ctx context.Context, db *gorm.DB, id uint64) error { @@ -136,7 +157,7 @@ func (br *RepoImpl[T]) DeleteByCond(ctx context.Context, cond any) error { if db := contextx.GetDb(ctx); db != nil { return br.DeleteByCondWithDb(ctx, db, cond) } - return gormx.DeleteByCond(br.getModel(), cond) + return gormx.DeleteByCond(br.GetModel(), cond) } func (br *RepoImpl[T]) DeleteByCondWithDb(ctx context.Context, db *gorm.DB, cond any) error { @@ -170,19 +191,15 @@ func (br *RepoImpl[T]) CountByCond(cond any) int64 { return gormx.CountByCond(br.GetModel(), cond) } -// getModel 获取表的模型实例 -func (br *RepoImpl[T]) getModel() T { - return br.M -} - // GetModel 获取表的模型实例 func (br *RepoImpl[T]) GetModel() T { - return br.getModel() + return br.M } // 从上下文获取登录账号信息,并赋值至实体 func (br *RepoImpl[T]) setBaseInfo(ctx context.Context, e T) T { if la := contextx.GetLoginAccount(ctx); la != nil { + // 默认使用数据库id策略, 若要改变则实体结构体自行覆盖SetBaseInfo方法。可参考 sys/entity.Resource e.SetBaseInfo(model.IdGenTypeNone, la) } return e diff --git a/server/pkg/model/model.go b/server/pkg/model/model.go index 4cbfdfdf..fc933808 100644 --- a/server/pkg/model/model.go +++ b/server/pkg/model/model.go @@ -21,8 +21,8 @@ const ( // 实体接口 type ModelI interface { - // id生成策略 - // IdGenType() IdGenType + // 是否为新建该实体模型, 默认 id == 0 为新建 + IsCreate() bool // 使用当前登录账号信息设置实体结构体的基础信息 // @@ -34,14 +34,13 @@ type IdModel struct { Id uint64 `json:"id"` } -// func (m *IdModel) IdGenType() IdGenType { -// // 默认由数据库自行生成 -// return IdGenTypeNone -// } +func (m *IdModel) IsCreate() bool { + return m.Id == 0 +} func (m *IdModel) SetBaseInfo(idGenType IdGenType, account *LoginAccount) { // 存在id,则赋值 - if m.Id != 0 { + if !m.IsCreate() { return } m.Id = GetIdByGenType(idGenType) @@ -70,7 +69,7 @@ type CreateModel struct { } func (m *CreateModel) SetBaseInfo(idGenType IdGenType, account *LoginAccount) { - if m.Id != 0 { + if !m.IsCreate() { return } @@ -98,7 +97,7 @@ type Model struct { // 设置基础信息. 如创建时间,修改时间,创建者,修改者信息 func (m *Model) SetBaseInfo(idGenType IdGenType, account *LoginAccount) { nowTime := time.Now() - isCreate := m.Id == 0 + isCreate := m.IsCreate() if isCreate { m.IsDeleted = ModelUndeleted m.CreateTime = &nowTime