package repository import ( "material_texture/internal/models" "gorm.io/gorm" "gorm.io/gorm/clause" ) type BindingRepository struct { db *gorm.DB } func NewBindingRepository(db *gorm.DB) *BindingRepository { return &BindingRepository{db: db} } // BindMaterial 绑定材质到多个group_id(幂等操作,使用upsert) // 优化: 分批处理,避免单条 SQL 过大 func (r *BindingRepository) BindMaterial(materialID int64, groupIDs []string) error { const batchSize = 1000 // 每批最多 1000 条 for i := 0; i < len(groupIDs); i += batchSize { end := i + batchSize if end > len(groupIDs) { end = len(groupIDs) } batch := groupIDs[i:end] bindings := make([]models.MaterialBinding, len(batch)) for j, groupID := range batch { bindings[j] = models.MaterialBinding{ MaterialID: materialID, GroupID: groupID, } } // 使用 ON CONFLICT DO NOTHING 实现幂等 if err := r.db.Clauses(clause.OnConflict{ Columns: []clause.Column{{Name: "material_id"}, {Name: "group_id"}}, DoNothing: true, }).Create(&bindings).Error; err != nil { return err } } return nil } // UnbindMaterial 解绑材质与指定的group_id func (r *BindingRepository) UnbindMaterial(materialID int64, groupIDs []string) error { return r.db.Where("material_id = ? AND group_id IN ?", materialID, groupIDs). Delete(&models.MaterialBinding{}).Error } // GetGroupsByMaterialID 根据材质ID获取所有关联的group_id (分页版本) func (r *BindingRepository) GetGroupsByMaterialID(materialID int64, page, pageSize int) ([]string, int64, error) { var groupIDs []string var total int64 db := r.db.Model(&models.MaterialBinding{}).Where("material_id = ?", materialID) // 获取总数 if err := db.Count(&total).Error; err != nil { return nil, 0, err } // 分页查询 offset := (page - 1) * pageSize err := db.Order("created_at DESC"). Offset(offset). Limit(pageSize). Pluck("group_id", &groupIDs).Error return groupIDs, total, err } // GetMaterialsByGroupIDs 根据多个group_id获取关联的材质(含材质详情) func (r *BindingRepository) GetMaterialsByGroupIDs(groupIDs []string) ([]models.GroupMaterialResult, error) { var bindings []models.MaterialBinding err := r.db.Preload("Material"). Where("group_id IN ?", groupIDs). Find(&bindings).Error if err != nil { return nil, err } results := make([]models.GroupMaterialResult, len(bindings)) for i, binding := range bindings { results[i] = models.GroupMaterialResult{ GroupID: binding.GroupID, Material: binding.Material, } } return results, nil } // DeleteByMaterialID 删除材质的所有绑定(材质删除时级联调用) func (r *BindingRepository) DeleteByMaterialID(materialID int64) error { return r.db.Where("material_id = ?", materialID). Delete(&models.MaterialBinding{}).Error }