package aliasmanagement import ( "context" "fmt" "git.x2erp.com/qdy/go-base/ctx" "git.x2erp.com/qdy/go-base/logger" "git.x2erp.com/qdy/go-base/model/response" "git.x2erp.com/qdy/go-base/util" "git.x2erp.com/qdy/go-db/factory/database" "git.x2erp.com/qdy/go-svc-configure/internal/tables" "github.com/google/uuid" "github.com/jmoiron/sqlx" ) // BatchSaveTableAlias 批量保存表别名字典 func BatchSaveTableAlias(req *BatchTableAliasRequest, ctx context.Context, dbFactory *database.DBFactory, reqCtx *ctx.RequestContext) *response.QueryResult[[]TableAliasDetail] { logger.Debug(fmt.Sprintf("BatchSaveTableAlias-开始批量保存表别名字典,数量: %d", len(req.Items))) // 参数验证 if len(req.Items) == 0 { logger.ErrorC(reqCtx, "批量保存的表别名字典列表不能为空") return util.CreateErrorResult[[]TableAliasDetail]("批量保存的表别名字典列表不能为空", reqCtx) } for i, item := range req.Items { if err := validateTableAliasRequest(&item); err != nil { logger.ErrorC(reqCtx, fmt.Sprintf("第%d个表别名参数验证失败: %v", i+1, err)) return util.CreateErrorResult[[]TableAliasDetail](fmt.Sprintf("第%d个表别名参数验证失败: %v", i+1, err), reqCtx) } } // 获取数据库连接并开始事务 db := dbFactory.GetDB() tx, err := db.BeginTxx(ctx, nil) if err != nil { logger.ErrorC(reqCtx, fmt.Sprintf("开始事务失败: %v", err)) return util.CreateErrorResult[[]TableAliasDetail](fmt.Sprintf("开始事务失败: %v", err), reqCtx) } defer func() { if p := recover(); p != nil { tx.Rollback() panic(p) } }() // 获取当前用户 creator := reqCtx.UserID if creator == "" { creator = "system" } var savedItems []TableAliasDetail var errors []string // 批量处理每个表别名 for i, item := range req.Items { logger.Debug(fmt.Sprintf("处理第%d个表别名: table_id=%s, table_alias=%s", i+1, item.TableID, item.TableAlias)) var tableAlias tables.DicTableAliasDB var processErr error // 检查表别名是否已存在(基于table_alias字段的唯一索引) aliasExists, err := checkTableAliasExists(ctx, tx, item.TableAlias) if err != nil { errors = append(errors, fmt.Sprintf("第%d个表别名检查存在性失败: %v", i+1, err)) continue } if aliasExists { // 更新表别名 tableAlias, processErr = updateTableAliasInBatch(ctx, tx, &item) if processErr != nil { errors = append(errors, fmt.Sprintf("第%d个表别名更新失败: %v", i+1, processErr)) continue } logger.Debug(fmt.Sprintf("更新表别名成功: %s", item.TableAlias)) } else { // 检查是否有软删除的记录 softDeletedExists, err := checkSoftDeletedTableAliasExists(ctx, tx, item.TableAlias) if err != nil { errors = append(errors, fmt.Sprintf("第%d个表别名检查软删除存在性失败: %v", i+1, err)) continue } if softDeletedExists { // 恢复软删除的表别名 tableAlias, processErr = restoreTableAliasInBatch(ctx, tx, &item) if processErr != nil { errors = append(errors, fmt.Sprintf("第%d个表别名恢复失败: %v", i+1, processErr)) continue } logger.Debug(fmt.Sprintf("恢复软删除表别名成功: %s", item.TableAlias)) } else { // 插入新的表别名 tableAlias, processErr = insertTableAliasInBatch(ctx, tx, &item, creator) if processErr != nil { errors = append(errors, fmt.Sprintf("第%d个表别名插入失败: %v", i+1, processErr)) continue } logger.Debug(fmt.Sprintf("插入表别名成功: %s", item.TableAlias)) } } // 添加保存成功的记录 detail := TableAliasDetail{ TableAlias: tableAlias, } savedItems = append(savedItems, detail) } // 如果有错误,回滚事务 if len(errors) > 0 { tx.Rollback() errorMsg := "" for i, errMsg := range errors { if i > 0 { errorMsg += "; " } errorMsg += errMsg } logger.ErrorC(reqCtx, fmt.Sprintf("批量保存表别名字典失败: %s", errorMsg)) return util.CreateErrorResult[[]TableAliasDetail](fmt.Sprintf("批量保存表别名字典失败: %s", errorMsg), reqCtx) } // 提交事务 if err := tx.Commit(); err != nil { logger.ErrorC(reqCtx, fmt.Sprintf("提交事务失败: %v", err)) return util.CreateErrorResult[[]TableAliasDetail](fmt.Sprintf("提交事务失败: %v", err), reqCtx) } logger.Debug(fmt.Sprintf("成功批量保存 %d 个表别名字典", len(savedItems))) return util.CreateSuccessResultData[[]TableAliasDetail](savedItems, reqCtx) } // updateTableAliasInBatch 批量更新中的表别名更新 func updateTableAliasInBatch(ctx context.Context, tx *sqlx.Tx, req *TableAliasRequest) (tables.DicTableAliasDB, error) { // 使用ID更新(如果提供ID),否则使用table_alias var query string var queryArgs []interface{} if req.ID != "" { query = ` UPDATE dic_table_alias SET table_id = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ? AND deleted_at IS NULL ` queryArgs = []interface{}{req.TableID, req.ID} } else { query = ` UPDATE dic_table_alias SET table_id = ?, updated_at = CURRENT_TIMESTAMP WHERE table_alias = ? AND deleted_at IS NULL ` queryArgs = []interface{}{req.TableID, req.TableAlias} } _, err := tx.ExecContext(ctx, query, queryArgs...) if err != nil { return tables.DicTableAliasDB{}, err } // 查询更新后的记录 var tableAlias tables.DicTableAliasDB selectQuery := ` SELECT id, table_id, table_alias, created_at, updated_at, deleted_at FROM dic_table_alias WHERE table_alias = ? AND deleted_at IS NULL ` err = tx.GetContext(ctx, &tableAlias, selectQuery, req.TableAlias) return tableAlias, err } // restoreTableAliasInBatch 批量恢复中的表别名恢复 func restoreTableAliasInBatch(ctx context.Context, tx *sqlx.Tx, req *TableAliasRequest) (tables.DicTableAliasDB, error) { query := ` UPDATE dic_table_alias SET deleted_at = NULL, table_id = ?, updated_at = CURRENT_TIMESTAMP WHERE table_alias = ? AND deleted_at IS NOT NULL ` _, err := tx.ExecContext(ctx, query, req.TableID, req.TableAlias, ) if err != nil { return tables.DicTableAliasDB{}, err } // 查询恢复后的记录 var tableAlias tables.DicTableAliasDB selectQuery := ` SELECT id, table_id, table_alias, created_at, updated_at, deleted_at FROM dic_table_alias WHERE table_alias = ? AND deleted_at IS NULL ` err = tx.GetContext(ctx, &tableAlias, selectQuery, req.TableAlias) return tableAlias, err } // insertTableAliasInBatch 批量插入中的表别名插入 func insertTableAliasInBatch(ctx context.Context, tx *sqlx.Tx, req *TableAliasRequest, creator string) (tables.DicTableAliasDB, error) { // 生成ID id := req.ID if id == "" { id = uuid.New().String() } query := ` INSERT INTO dic_table_alias (id, table_id, table_alias, created_at, updated_at) VALUES (?, ?, ?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP) ` _, err := tx.ExecContext(ctx, query, id, req.TableID, req.TableAlias, ) if err != nil { return tables.DicTableAliasDB{}, err } // 查询刚插入的记录 var tableAlias tables.DicTableAliasDB selectQuery := ` SELECT id, table_id, table_alias, created_at, updated_at, deleted_at FROM dic_table_alias WHERE table_alias = ? AND deleted_at IS NULL ` err = tx.GetContext(ctx, &tableAlias, selectQuery, req.TableAlias) return tableAlias, err }