goji + mysql 例子
🕡 Thu, 25 Feb 2016 by GolangNote
goji + mysql 例子
// library/database/engine.go
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
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
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
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
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/ 2
本文网址: https://golangnote.com/topic/117.html (转载注明出处)
关于GolangNote:记录在工作中使用golang 遇到、面临的相关问题及解决方法。如果你在这里获得一些知识或信息,解决你的编程问题,请考虑捐赠给不幸的人或者你喜欢的慈善机构,除捐赠外,种植树木、志愿服务或减少排碳的行为也很有益处。如果你有任何问题可以在下面 留言
Be the first to comment!
Relative Articles
Recent Go Articles
- Golang 把cookie 字符串解析为cookie 结构
- Golang 计算字符串中包含某个或某些字符集的个数
- 使用Golang 对文件增删写读操作备忘
- Go Modules 使用备忘
- 使用Golang 简单删除图片exif 信息
- 谷歌翻译的 golang 库推荐
- Go 1.13.2 与1.13.3 紧急更新
- golang 人脸检测识别库
- Go build 错误 “stackcheck redeclared in this block previous declaration”的解决方法
- Golang phantomjs 动态代理实现
- Golang chrome debug protocol 库推荐
- Golang 随机打乱数组/Slice
- Golang sync.WaitGroup 的 Wait 超时处理
- Golang实现简单的Socks5代理
- Golang 用snappy + Base64 简单压缩加密进行网络传输
- Golang http IPv4/IPv6 服务
- golang 全角半角相互转换
- 在自己的网站部署TLS 1.3
- Golang 实现/打印菜单树
- Golang telegram 机器人小试
Top Go Articles
- golang 人脸检测识别库
- Golang 时区时差处理方式
- golang 把上传文件转为byte
- GoLang Map key 排序输出的例子
- go 获取硬盘的可用空间的方法
- golang 实现python 的dict.keys() dict.values() 函数
- golang 原生xml 转json
- Golang slice 和 map 的查询性能比较
- Caddy、 SSLDocker、Nginx 性能比较及使用体验
- Golang io.ReadCloser 和[]byte 相互转化的方法
- Golang 减小gc 压力、避免内存泄漏小tips
- Golang telegram 机器人小试
- GoLang 遍历目录的不同方法
- Golang 字符串毫秒转时间格式
- iris websocket 自定义信息结构
- golang 正确获取绝对路径的方法
- Golang 随机打乱数组/Slice
- 在go web 应用里避免全局变量
- 关于Golang msgpack 和 json 性能的简单比较
- Golang 合并byte 的性能比较