17
3

始めました!株式会社メタップスホールディングスのジュリアンです!

今回の紹介はGo言語のGormライブラリの2件の違いを説明させてください。

Gorm ライブラリの紹介

デベロッパーフレンドリーを目指した、Go言語のORMライブラリです。DBと連携出来て、mysql、postgreなどのクエリが出来るようになります。

Gormのバージョン1からv1.9.16まではgithub.com/jinzhu/gormに保存されており、あなたのコードからインポートするにはそのパスを使う.

Goの慣例では、新しいパッケージ・バージョンが後方互換性を失った場合、インポート・パスを変更する必要がある。そこで、バージョン2をリリースする際、チームはgithubの新しい組織( https://github.com/go-gorm/gorm )にレポを移動することにした。この新しいバージョンは、gorm.io/gormを使ってあなたのコードにインポートされる.

import (
    ...
    "gorm.io/gorm"
)

(goのエコシステムのクセのため、v2はv1.20.0以上とタグ付けされていることを覚えておいてください。)

トランザクションが一番違いです

jinzhu/gorm

古いGormのやり方はまだtransaction自身を自分で管理します。
最初はBeginをして、トランザクジョンを確認して、RollbackUnlessCommittedをdeferにお願いして、作成されたらLastで作成されたオブジェクトを取って、returnします。

func (repository *someRepository) CreateTask(entity *some.Task) (*some.Task, error) {

    tx := repository.DB.Begin()
	if tx.Error != nil {
		return nil, errors.Wrap(tx.Error, "failed to begin transaction")
	}

	defer func() {
		if err := tx.RollbackUnlessCommitted().Error; err != nil {
			log.Error("failed to rollback transaction", zap.Error(err))
		}
	}()

	if err := tx.Create(entity).Error; err != nil {
		return nil, errors.Wrap(err, "failed to create task")
	}

	var lastEntity some.Task
	if err := tx.Last(&lastEntity).Error; err != nil {
		return nil, errors.Wrap(err, "failed to get last task")
	}

	if err := tx.Commit().Error; err != nil {
		return nil, errors.Wrap(err, "failed to commit while creating task")
	}

	return &lastEntity, nil
 }

gorm.io

今回は全部同じメソットでまとめるようになってます!それでLastを使わないくてもそのままにentityがメモリに残ってます!


func (repository *someRepository) CreateTask(entity *some.Task) error {
    return repository.gormIOdb.Transaction(func(tx *gormio.DB) error {
    	if err := tx.Create(&entity).Error; err != nil {
			return errors.Wrap(err, "failed to create task")
		}
        return nil
    }
}

Transactionのメソットの中を見ると色々を任せ出来ます!

// Transaction start a transaction as a block, return error will rollback, otherwise to commit. Transaction executes an
// arbitrary number of commands in fc within a transaction. On success the changes are committed; if an error occurs
// they are rolled back.
func (db *DB) Transaction(fc func(tx *DB) error, opts ...*sql.TxOptions) (err error) {
	panicked := true

	if committer, ok := db.Statement.ConnPool.(TxCommitter); ok && committer != nil {
		// nested transaction
		if !db.DisableNestedTransaction {
			err = db.SavePoint(fmt.Sprintf("sp%p", fc)).Error
			if err != nil {
				return
			}
			defer func() {
				// Make sure to rollback when panic, Block error or Commit error
				if panicked || err != nil {
					db.RollbackTo(fmt.Sprintf("sp%p", fc))
				}
			}()
		}
		err = fc(db.Session(&Session{NewDB: db.clone == 1}))
	} else {
		tx := db.Begin(opts...)
		if tx.Error != nil {
			return tx.Error
		}

		defer func() {
			// Make sure to rollback when panic, Block error or Commit error
			if panicked || err != nil {
				tx.Rollback()
			}
		}()

		if err = fc(tx); err == nil {
			panicked = false
			return tx.Commit().Error
		}
	}

	panicked = false
	return
}

CommitのステータスやまたはBeginがメソットに入ってます!deferも自分でしなくてもTransactionが全部やってます!

まとめ

Gorm v2は、構文や機能はv1にかなり近いですが、より強力で一貫性があり、多くのバグが取り除かれています。ベンチマークはまだ見ていませんが、プリペアドステートメントを使用することにより、より高性能になっているはずです。

全体として、新しいプロジェクトでv2を使わない理由はないし、既存のプロジェクトでv1から移行する理由もたくさんある。

17
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
3