Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SQL操作でのトランザクション制御 #13

Open
shoken3207 opened this issue Jan 9, 2025 · 0 comments
Open

SQL操作でのトランザクション制御 #13

shoken3207 opened this issue Jan 9, 2025 · 0 comments

Comments

@shoken3207
Copy link
Owner

1個のAPIで複数のテーブルを変更する場合、一貫性を持たせるためにトランザクション制御が必要

func (s *ExpeditionService) CreateExpedition(newExpedition *models.Expedition, images []models.ExpeditionImage, games []models.Game) error {
    // トランザクションを開始
    return db.DB.Transaction(func(tx *gorm.DB) error {
        // 遠征記録の作成
        if err := tx.Create(newExpedition).Error; err != nil {
            return utils.NewCustomError(http.StatusInternalServerError, "遠征記録の作成に失敗しました")
        }

        // 画像の作成
        for _, image := range images {
            image.ExpeditionId = newExpedition.ID
            if err := tx.Create(&image).Error; err != nil {
                return utils.NewCustomError(http.StatusInternalServerError, "遠征記録の画像の作成に失敗しました")
            }
        }

        // 試合記録の作成
        for _, game := range games {
            game.ExpeditionId = newExpedition.ID
            if err := tx.Create(&game).Error; err != nil {
                return utils.NewCustomError(http.StatusInternalServerError, "試合記録の作成に失敗しました")
            }
        }

        return nil
    })
}

func (s *ExpeditionService) UpdateExpedition(expeditionId uint, userId uint, updateData *models.Expedition, newImages []models.ExpeditionImage, deleteImageIds []uint) error {
    return db.DB.Transaction(func(tx *gorm.DB) error {
        // 遠征記録の存在確認と所有者チェック
        var expedition models.Expedition
        if err := tx.First(&expedition, expeditionId).Error; err != nil {
            if errors.Is(err, gorm.ErrRecordNotFound) {
                return utils.NewCustomError(http.StatusNotFound, "遠征記録が見つかりません")
            }
            return utils.NewCustomError(http.StatusInternalServerError, "遠征記録の取得に失敗しました")
        }

        if expedition.UserId != userId {
            return utils.NewCustomError(http.StatusForbidden, "この遠征記録を更新する権限がありません")
        }

        // 遠征記録の更新
        if err := tx.Model(&expedition).Updates(updateData).Error; err != nil {
            return utils.NewCustomError(http.StatusInternalServerError, "遠征記録の更新に失敗しました")
        }

        // 指定された画像の削除
        if len(deleteImageIds) > 0 {
            if err := tx.Where("id IN ?", deleteImageIds).Delete(&models.ExpeditionImage{}).Error; err != nil {
                return utils.NewCustomError(http.StatusInternalServerError, "遠征記録の画像の削除に失敗しました")
            }
        }

        // 新しい画像の追加
        for _, image := range newImages {
            image.ExpeditionId = expeditionId
            if err := tx.Create(&image).Error; err != nil {
                return utils.NewCustomError(http.StatusInternalServerError, "遠征記録の画像の作成に失敗しました")
            }
        }

        return nil
    })
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant