goji + mysql 例子
完整的例子
// library/database/engine.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package database
import (
"fmt"
"time"
_ "github.com/go-sql-driver/mysql" // load mysql driver for xorm
"github.com/go-xorm/core"
"github.com/go-xorm/xorm"
)
var engine *xorm.Engine
func init() {
loc, err := time.LoadLocation("UTC")
if err != nil {
panic(err)
}
time.Local = loc
}
// UseEngine reutrns db resource
func UseEngine() *xorm.Engine {
if engine == nil {
engine = initEngine()
}
return engine
}
func initEngine() *xorm.Engine {
dbUser := "user"
dbPass := "pass"
dbHost := "127.0.0.1"
dbPort := 3306
dbName := "blogdb"
dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s", dbUser, dbPass, dbHost, dbPort, dbName)
e, err := xorm.NewEngine("mysql", dsn)
if err != nil {
panic(err)
}
// as default mapper, underscore is inserted on every capital case for table or field name.
// (e.g.) UserID => user_i_d, IPAddress => i_p_address
// to prevent this rule, use GonicMapper.
e.SetMapper(core.NewCacheMapper(new(core.GonicMapper)))
err = e.Ping()
if err != nil {
panic(err)
}
return e
}
Go 默认使用连接池,所以把数据链接放在全局变量。同时设置UTC时区,贯穿整个应用。
把数据链接保存在 context 里
// library/net/context/resource/resource_database.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
package resource
import (
"github.com/go-xorm/xorm"
"golang.org/x/net/context"
"github.com/eure/example-blog-golang/library/database"
)
// GetDB returns database engine
func GetDB(c context.Context) *xorm.Engine {
v, ok := c.Value("database").(*xorm.Engine)
if !ok {
return nil
}
return v
}
// UseDB returns database engine
func UseDB(c context.Context) *xorm.Engine {
db := GetDB(c)
if db == nil {
db = database.UseEngine()
c = context.WithValue(c, "database", db)
}
return db
}
// UseTx returns database transaction
func UseTx(c context.Context) *xorm.Session {
tx := c.Value("transaction").(*xorm.Session)
if tx == nil {
db := UseDB(c)
tx := db.NewSession()
tx.Begin()
c = context.WithValue(c, "transaction", tx)
}
return tx
}
// Commit commits database transaction
func Commit(c context.Context) error {
tx := c.Value("transaction").(*xorm.Session)
if tx == nil {
return nil
}
err := tx.Commit()
if err != nil {
return err
}
c = context.WithValue(c, "transaction", nil)
tx.Close()
return nil
}
// Rollback rollbacks database transaction
func Rollback(c context.Context) error {
tx := c.Value("transaction").(*xorm.Session)
if tx == nil {
return nil
}
err := tx.Rollback()
if err != nil {
return err
}
c = context.WithValue(c, "transaction", nil)
tx.Close()
return nil
}
// Release releases all resources
func Release(c context.Context) {
if c == nil {
return
}
tx := c.Value("transaction").(*xorm.Session)
if tx != nil {
tx.Close()
}
}
用户model
// model/author/author_entity.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package author
import (
"fmt"
)
// Entity is struct for author
type Entity struct {
Email string `response:"email" xorm:"pk not null unique"`
Name string `response:"name" xorm:"not null unique"`
}
const (
tableName = "authors"
pkName = "email"
)
// TableName define table name for Xorm
func (e Entity) TableName() string {
return tableName
}
func (e Entity) String() string {
return fmt.Sprintf("{email: %s, name: %s}", e.Email, e.Name)
}
建立文件
// model/root_repository.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
package model
import (
"fmt"
"github.com/go-xorm/xorm"
"golang.org/x/net/context"
"github.com/eure/example-blog-golang/library/net/context/resource"
)
// RootRepository is root struct for all repositories
type RootRepository struct {
Ctx context.Context
Engine *xorm.Engine
PrimaryKey string
Seed interface{}
omitList []string
}
// NewRootRepositoryWithSeed creates new RootRepository
func NewRootRepositoryWithSeed(ctx context.Context, pk string, seed interface{}) *RootRepository {
return &RootRepository{
Ctx: ctx,
Engine: resource.UseDB(ctx),
PrimaryKey: pk,
Seed: seed,
}
}
// ============================================================
// helper
// ============================================================
// NewSession return session
func (r *RootRepository) NewSession() *xorm.Session {
return r.Engine.NewSession()
}
// AddOmit adds column name to omit list
func (r *RootRepository) AddOmit(col string) {
r.omitList = append(r.omitList, col)
}
// GetLastSQL returns the executed SQL statement
func (r *RootRepository) GetLastSQL(s *xorm.Session) string {
sql, args := s.LastSQL()
return fmt.Sprintf("%s -- [args] %v", sql, args)
}
// ============================================================
// create
// ============================================================
// CreateOne inserts new entity data to database
func (r *RootRepository) CreateOne(e interface{}) error {
s := r.Engine.NewSession()
if len(r.omitList) > 0 {
for _, col := range r.omitList {
s.Omit(col)
}
r.omitList = []string{}
}
_, err := s.Insert(e)
if err != nil {
return err
}
return nil
}
// ============================================================
// get
// ============================================================
// GetOneByPK fetches a single row by primary key
func (r *RootRepository) GetOneByPK(ent, pk interface{}) (bool, error) {
s := r.Engine.NewSession()
s.And(r.PrimaryKey+" = ?", pk)
return r.GetOneBySession(s, ent)
}
// GetOneBySession fetches a single row using the given session
func (r *RootRepository) GetOneBySession(s *xorm.Session, ent interface{}) (bool, error) {
has, err := s.Get(ent)
if err != nil {
return has, err
}
return has, nil
}
Author repository
// model/author/author_repository.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package author
import (
"golang.org/x/net/context"
"github.com/eure/example-blog-golang/model"
)
// Repository is repo for author
type Repository struct {
*model.RootRepository
}
// NewRepository creates new Repository
func NewRepository(ctx context.Context) *Repository {
return &Repository{
RootRepository: model.NewRootRepositoryWithSeed(ctx, pkName, new(Entity)),
}
}
// GetByEmail fetches a single author by email
func (r *Repository) GetByEmail(email string) *Entity {
ent := new(Entity)
has, err := r.GetOneByPK(ent, email)
switch {
case err != nil:
// TODO: logging
return nil
case !has:
return nil
}
return ent
}
摘自 https://developers.eure.jp/go-language/advent-calendar-20/
本文网址: https://golangnote.com/topic/117.html 转摘请注明来源