fix: wrap AssignRoles in transaction and eliminate N+1 queries

- AssignRoles: wrap DeleteByUserID + BatchCreate in DB transaction (P1)
- GetUserRoles: use GetByIDs batch query instead of per-role GetByID loop (N+1 fix)
- ListAdmins: use GetByIDs batch query instead of per-user GetByID loop (N+1 fix)
- Add WithTx/DB methods to UserRoleRepository for transaction support
- Add GetByIDs to UserRepository (batch user lookup)
- Add .gitattributes to normalize line endings to LF (P2)
This commit is contained in:
2026-04-11 10:32:33 +08:00
parent 8c1cf54213
commit c2096ff008
4 changed files with 77 additions and 24 deletions

View File

@@ -31,6 +31,11 @@ func NewUserRepository(db *gorm.DB) *UserRepository {
return &UserRepository{db: db}
}
// DB returns the underlying GORM DB for transaction support
func (r *UserRepository) DB() *gorm.DB {
return r.db
}
// Create 创建用户
func (r *UserRepository) Create(ctx context.Context, user *domain.User) error {
return r.db.WithContext(ctx).Create(user).Error
@@ -56,6 +61,19 @@ func (r *UserRepository) GetByID(ctx context.Context, id int64) (*domain.User, e
return &user, nil
}
// GetByIDs 批量获取用户(消除 N+1 查询)
func (r *UserRepository) GetByIDs(ctx context.Context, ids []int64) ([]*domain.User, error) {
if len(ids) == 0 {
return []*domain.User{}, nil
}
var users []*domain.User
err := r.db.WithContext(ctx).Where("id IN ?", ids).Find(&users).Error
if err != nil {
return nil, err
}
return users, nil
}
// GetByUsername 根据用户名获取用户
func (r *UserRepository) GetByUsername(ctx context.Context, username string) (*domain.User, error) {
var user domain.User

View File

@@ -18,6 +18,16 @@ func NewUserRoleRepository(db *gorm.DB) *UserRoleRepository {
return &UserRoleRepository{db: db}
}
// DB returns the underlying GORM DB for transaction support
func (r *UserRoleRepository) DB() *gorm.DB {
return r.db
}
// WithTx returns a new repository instance that uses the given transaction
func (r *UserRoleRepository) WithTx(tx *gorm.DB) *UserRoleRepository {
return &UserRoleRepository{db: tx}
}
// Create 创建用户角色关联
func (r *UserRoleRepository) Create(ctx context.Context, userRole *domain.UserRole) error {
return r.db.WithContext(ctx).Create(userRole).Error