LoginSignup
3
4

More than 5 years have passed since last update.

GoでORMライブラリまわりを綺麗に書く

Last updated at Posted at 2017-11-09

GoのWebアプリケーションで、ORM周りを綺麗に書くTipsです。
今回の例では、ORMにgo-gorpを使ってます。

サービス層からマッパー層使うときに、gorpを直接触りたくないのと、
いちいちerror判定を入れるのが面倒なので、チェインで書けるようにしてみました。

コード一部の記載なので、よしなに参考にしてください。

Before

マッパーがgorpを外に教えちゃうと

mapper.go
// どこかで初期化する
var tx *gorp.Transaction

func GetTransaction *gorp.Transaction {
    return tx
}

サービスの全funcで、こんだけのエラー判定ずっと書くのヤバい・・・。
gorpに依存してるのも嫌だ。

service.go
// 例)UserとSessionを作成してSessionを返す
func (s *Service) CreateUserAndSession() (*model.Session, error) {
    // *gorp.Transaction
    tx, errBegin := mapper.GetTransaction()
    if errBegin != nil {
        return nil, errBegin
    }

    u := model.NewUser()
    if errIns1 := tx.Insert(u); errIns1 != nil {
        return nil, errIns1
    }

    s := model.NewSession(u.ID)
    if errIns2 := tx.Insert(s); errIns2 != nil {
        return nil, errIns2
    }

    if errCommit := tx.Commit().Commit(); errCommit != nil {
        return nil, errCommit
    }
    return s, nil
}

After

マッパーの方で、一枚噛ませるようにして、エラーも内包すると。

mapper.go
package mapper

type MyTransaction struct {
    tx  *gorp.Transaction
    err error
}

func Begin() *MyTransaction {
    tx, err = gorp.dbMap.Begin()
    return &MyTransaction {
        tx:  tx,
        err: err,
    }
}

// CRUDをラップしてチェインできるように
func (t* MyTransaction) Insert(m *interface{}) *MyTransaction {
    if t.err == nil {
        t.err = t.tx.Insert(m)
    }
    return t
}

// 最後のコミット時にerrorを返す
func (t* MyTransaction) Commit(m *interface{}) error {
    if t.err != nil {
        return t.err
    }
    return t.tx.Commit()
}

サービス側がスッキリ。
error発生しても全てをリレーするため若干パフォーマンス勿体無いですが、
それが常時起こるような構造の方を改善すべきで、コードの保守性のメリットが大きいかなと思います。

service.go
package service

func (s *Service) CreateUserAndSession() (*model.Session, error) {
    u := model.NewUser()
    s := model.NewSession(u.ID)
    if err := mapper.Begin().Insert(u).Insert(s).Commit(); err != nil {
        return nil, err
    }
    return s, nil
}

3
4
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
3
4