分享
  1. 首页
  2. 文章

使用 orm 实现增删改查 - beego 框架使用笔记

play · · 1933 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

概述

beego ORM 是一个强大的 Go 语言 ORM 框架,目前该框架已支持 MySQL、PostgreSQL、Sqlite3 数据库驱动。

安装 ORM

go get github.com/astaxie/beego/orm
复制代码

初始化

创建项目

使用 bee 工具的安装 api 命令 bee api apiproject 创建 apiproject 项目,具体使用方法查看 beego api 命令

模型关系

# 外键始终在子表上
# 一个用户对应一个简介;一个简介对应一个用户;
one2one:User(子表) -> Profile(主表);one2one:Profile -> User 
复制代码

结构体

type User struct {
 Id int `json:"id"`
 Username string `json:"username"`
 Password string `json:"password"`
 Profile *Profile `orm:"rel(one)" json:"profile"` // OneToOne relation
}
type Profile struct {
 Id int `json:"id"`
 Gender int `json:"gender"`
 Age int `json:"age"`
 Address string `json:"address"`
 Email string `json:"email"`
 User *User `orm:"reverse(one)" json:"-"` // 设置一对一反向关系(可选)
}
复制代码
使用标签`orm:"column(id)`对属性进行标注,用于解析。
`orm:"rel(one)"` 表示one2one
`orm:"reverse(one)"` `orm:"reverse(one)"` 标注反向关系
复制代码

database 信息

注册 model:

orm.RegisterModel(new(User), new(Profile))
复制代码

自定义表名:

func (u *User) TableName() string {
	return "users"
}
func (u *Profile) TableName() string {
	return "users_profiles"
}
复制代码

自动建表:

orm.RunSyncdb("default", false, true)
复制代码

数据表结构:

mysql> show tables;
+-------------------+
| Tables_in_play_db |
+-------------------+
| users |
| users_profiles |
+-------------------+
2 rows in set (0.01 sec)
mysql> desc users;
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| username | varchar(255) | NO | | | |
| password | varchar(255) | NO | | | |
| profile_id | int(11) | NO | UNI | NULL | |
+------------+--------------+------+-----+---------+----------------+
4 rows in set (0.02 sec)
mysql> desc users_profiles;
+---------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| gender | int(11) | YES | | 0 | |
| age | int(11) | YES | | 0 | |
| address | varchar(255) | YES | | | |
| email | varchar(255) | YES | | | |
+---------+--------------+------+-----+---------+----------------+
5 rows in set (0.01 sec)
复制代码

功能实现

项目参数配置

/apiproject/conf/app.conf

appname = apiproject
httpport = 8090
runmode = dev
autorender = false
copyrequestbody = true
EnableDocs = true
sqlconn = root:123456@/play_db?charset=utf8
复制代码

通用 utils

分页:
/apiproject/utils/page.go

package utils
var (
	PageSize int = 10
)
type Page struct {
	Page 	int `json:"page"`
	PageSize	int `json:"pageSize"`
	TotalPage	int `json:"totalPage"`
	TotalCount	int `json:"totalCount"`
	FirstPage	bool `json:"firstPage"`
	LastPage	bool `json:"lastPage"`
	List		interface{} `json:"list"`
}
func Pagination(count int, page int, pageSize int, list interface{}) Page {
	tp := count / pageSize
	if count%pageSize > 0 {
		tp = count/pageSize + 1
	}
	return Page{Page: page, PageSize: pageSize, TotalPage: tp, TotalCount: count, FirstPage: page == 1, LastPage: page == tp, List: list}
}
复制代码

main 入口

/apiproject/main.go

package main
import (
	_ "apiproject/routers"
	"github.com/astaxie/beego/orm"
	"github.com/astaxie/beego"
	_ "github.com/go-sql-driver/mysql"
)
func init() {
	// 参数1 driverName
	// 参数2 数据库类型
	// 这个用来设置 driverName 对应的数据库类型
	// mysql / sqlite3 / postgres 这三种是默认已经注册过的,所以可以无需设置
	// orm.RegisterDriver("mysql", orm.DRMySQL)
	// ORM 必须注册一个别名为 default 的数据库,作为默认使用。
	// 参数1		数据库的别名,用来在 ORM 中切换数据库使用
	// 参数2		driverName
	// 参数3		对应的链接字符串
	orm.RegisterDataBase("default", "mysql", beego.AppConfig.String("sqlconn"))
}
func main() {
	if beego.BConfig.RunMode == "dev" {
		beego.BConfig.WebConfig.DirectoryIndex = true
		beego.BConfig.WebConfig.StaticDir["/swagger"] = "swagger"
	}
	// 开启 orm 调试模式:开发过程中建议打开,release时需要关闭
	orm.Debug = true
	beego.Run()
}
复制代码

路由实现

RESTful Controller 路由,初始化 namespace:
/apiproject/routers/router.go

// @APIVersion 1.0.0
// @Title apiproject API
// @License Apache 2.0
package routers
import (
	"apiproject/controllers"
	"github.com/astaxie/beego"
)
func init() {
	ns := beego.NewNamespace("/v1",
		beego.NSNamespace("/object",
			beego.NSInclude(
				&controllers.ObjectController{},
			),
		),
		beego.NSNamespace("/user",
			beego.NSInclude(
				&controllers.UserController{},
			),
		),
	)
	beego.AddNamespace(ns)
}
复制代码

/apiproject/routers/commentsRouter_controllers.go

package routers
import (
	"github.com/astaxie/beego"
	"github.com/astaxie/beego/context/param"
)
func init() {
 beego.GlobalControllerRouter["apiproject/controllers:UserController"] = append(beego.GlobalControllerRouter["apiproject/controllers:UserController"],
 beego.ControllerComments{
 Method: "Post",
 Router: `/`,
 AllowHTTPMethods: []string{"post"},
 MethodParams: param.Make(),
 Filters: nil,
 Params: nil})
 beego.GlobalControllerRouter["apiproject/controllers:UserController"] = append(beego.GlobalControllerRouter["apiproject/controllers:UserController"],
 beego.ControllerComments{
 Method: "GetAll",
 Router: `/`,
 AllowHTTPMethods: []string{"get"},
 MethodParams: param.Make(),
 Filters: nil,
 Params: nil})
 beego.GlobalControllerRouter["apiproject/controllers:UserController"] = append(beego.GlobalControllerRouter["apiproject/controllers:UserController"],
 beego.ControllerComments{
 Method: "Get",
 Router: `/:uid`,
 AllowHTTPMethods: []string{"get"},
 MethodParams: param.Make(),
 Filters: nil,
 Params: nil})
 beego.GlobalControllerRouter["apiproject/controllers:UserController"] = append(beego.GlobalControllerRouter["apiproject/controllers:UserController"],
 beego.ControllerComments{
 Method: "Put",
 Router: `/:uid`,
 AllowHTTPMethods: []string{"put"},
 MethodParams: param.Make(),
 Filters: nil,
 Params: nil})
 beego.GlobalControllerRouter["apiproject/controllers:UserController"] = append(beego.GlobalControllerRouter["apiproject/controllers:UserController"],
 beego.ControllerComments{
 Method: "Delete",
 Router: `/:uid`,
 AllowHTTPMethods: []string{"delete"},
 MethodParams: param.Make(),
 Filters: nil,
 Params: nil})
}
复制代码

controller 实现

通用 controller base:
/apiproject/controllers/base.go

package controllers
import (
	"github.com/astaxie/beego"
)
type BaseController struct {
	beego.Controller
}
// Response 结构体
type Response struct {
	Code int `json:"code"`
	Message string `json:"message"`
	Data interface{} `json:"data"`
}
// Error Response 结构体
type ErrResponse struct {
	Code int `json:"code"`
	Message string `json:"message"`
}
复制代码

自定义错误代码编码:
/apiproject/controllers/code.go

package controllers
var (
	// Common errors
	SUCCESS = &Errno{Code: 0, Message: "成功"}
	InternalServerError = &Errno{Code: 10001, Message: "内部服务错误"}
	ErrBind = &Errno{Code: 10002, Message: "参数错误"}
	ErrDatabase = &Errno{Code: 20001, Message: "数据库错误"}
	ErrToken = &Errno{Code: 20002, Message: "签发令牌出错"}
	ErrNoPermission = &Errno{Code: 20003, Message: "无权限"}
	// user errors
	ErrUserNotFound = &Errno{Code: 20101, Message: "用户未注册"}
	ErrUserExist = &Errno{Code: 20102, Message: "用户已存在"}
)
复制代码

通用错误处理:
/apiproject/controllers/errno.go

package controllers
import "fmt"
type Errno struct {
	Code int
	Message string
}
func (err Errno) Error() string {
	return err.Message
}
// Err represents an error
type Err struct {
	Code int
	Message string
	Err error
}
func New(errno *Errno, err error) *Err {
	return &Err{Code: errno.Code, Message: errno.Message, Err: err}
}
func (err *Err) Add(message string) error {
	err.Message += " " + message
	return err
}
func (err *Err) Addf(format string, args ...interface{}) error {
	err.Message += " " + fmt.Sprintf(format, args...)
	return err
}
func (err *Err) Error() string {
	return fmt.Sprintf("Err - code: %d, message: %s, error: %s", err.Code, err.Message, err.Err)
}
func IsErrUserNotFound(err error) bool {
	code, _ := DecodeErr(err)
	return code == ErrUserNotFound.Code
}
func DecodeErr(err error) (int, string) {
	if err == nil {
		return SUCCESS.Code, SUCCESS.Message
	}
	switch typed := err.(type) {
	case *Err:
		return typed.Code, typed.Message
	case *Errno:
		return typed.Code, typed.Message
	default:
	}
	return InternalServerError.Code, err.Error()
}
复制代码

用户 controller 模块:
/apiproject/controllers/user.go

package controllers
import (
	"apiproject/models"
	"apiproject/utils"
	"encoding/json"
	"strconv"
)
// Operations about Users
type UserController struct {
	BaseController
}
// @Title CreateUser
// @Description create users
// @Param	body		body 	models.User	true		"body for user content"
// @Success 200 {int} models.User.Id
// @Failure 403 body is empty
// @router / [post]
func (u *UserController) Post() {
	var user models.User
	_ = json.Unmarshal(u.Ctx.Input.RequestBody, &user)
	uid, _ := models.AddUser(user)
	u.Data["json"] = map[string]int64{"uid": uid}
	u.ServeJSON()
}
// @Title GetAll
// @Description get all Users
// @Success 200 {object} models.User
// @router / [get]
func (u *UserController) GetAll() {
	currentPage, _ := strconv.Atoi(u.Ctx.Input.Query("page"))
	if currentPage == 0 {
		currentPage = 1
	}
	pageSize := utils.PageSize
	d , err:= models.GetAllUsers(currentPage,pageSize)
	code, message := DecodeErr(err)
	if err != nil {
		u.Data["json"] = ErrResponse{code, message}
	} else {
		u.Data["json"] = Response{code, message, d}
	}
	u.ServeJSON()
}
// @Title Get
// @Description get user by uid
// @Param	uid		path 	string	true		"The key for staticblock"
// @Success 200 {object} models.User
// @Failure 403 :uid is empty
// @router /:uid [get]
func (u *UserController) Get() {
	uid, _ := u.GetInt(":uid")
	if uid > 0 {
		user, err := models.GetUser(uid)
		code, message := DecodeErr(err)
		if err != nil {
			u.Data["json"] = ErrResponse{code, message}
		} else {
			u.Data["json"] = Response{code, message, user}
		}
	}
	u.ServeJSON()
}
// @Title Update
// @Description update the user
// @Param	uid		path 	string	true		"The uid you want to update"
// @Param	body		body 	models.User	true		"body for user content"
// @Success 200 {object} models.User
// @Failure 403 :uid is not int
// @router /:uid [put]
func (u *UserController) Put() {
	uid, _ := u.GetInt(":uid")
	if uid > 0 {
		var user models.User
		_ = json.Unmarshal(u.Ctx.Input.RequestBody, &user)
		uu, err := models.UpdateUser(uid, &user)
		code, message := DecodeErr(err)
		if err != nil {
			u.Data["json"] = ErrResponse{code, message}
		} else {
			u.Data["json"] = Response{code, message, uu}
		}
	}
	u.ServeJSON()
}
// @Title Delete
// @Description delete the user
// @Param	uid		path 	string	true		"The uid you want to delete"
// @Success 200 {string} delete success!
// @Failure 403 uid is empty
// @router /:uid [delete]
func (u *UserController) Delete() {
	uid, _ := u.GetInt(":uid")
	b, err := models.DeleteUser(uid)
	code, message := DecodeErr(err)
	if err != nil {
		u.Data["json"] = ErrResponse{code, message}
	} else {
		u.Data["json"] = Response{code, message, b}
	}
	u.ServeJSON()
}
复制代码

model 实现

用户 model 模块,orm 实现 增删改查:
/apiproject/models/user.go

package models
import (
	"apiproject/utils"
	"errors"
	"github.com/astaxie/beego/orm"
	"strconv"
)
type User struct {
 Id int `json:"id"`
 Username string `json:"username"`
 Password string `json:"password"`
 Profile *Profile `orm:"rel(one)" json:"profile"` // OneToOne relation
}
type Profile struct {
 Id int `json:"id"`
 Gender int `json:"gender"`
 Age int `json:"age"`
 Address string `json:"address"`
 Email string `json:"email"`
 User *User `orm:"reverse(one)" json:"-"` // 设置一对一反向关系(可选)
}
// 自定义表名
func (u *User) TableName() string {
	return "users"
}
func (u *Profile) TableName() string {
	return "users_profiles"
}
// 新增用户
func AddUser(u User) (id int64, err error) {
	// one2one 插入
	// 创建一个 ormer 对象
	o := orm.NewOrm()
	// 开启事务
	err = o.Begin()
	// 插入主表
	profile := Profile{
		Gender: u.Profile.Gender,
		Age: u.Profile.Age,
		Address: u.Profile.Address,
		Email: u.Profile.Email}
	id, err = o.Insert(&profile)
	if err != nil {
		// 回滚事务
		err = o.Rollback()
	}
	// 插入子表
	user := User{
		Username: u.Username,
		Password: u.Password,
		Profile: &Profile{Id: int(id)}}
	_, err = o.Insert(&user)
	if err != nil {
		// 回滚事务
		err = o.Rollback()
	}
	// 提交事务
	err = o.Commit()
	return id, err
}
// 查询指定用户
func GetUser(uid int) (u *User, err error) {
	o := orm.NewOrm()
	user := &User{Id: uid}
	err = o.Read(user)
	// 已经取得了 Users 对象,查询 UserProfiles
	if user.Profile != nil {
		err = o.Read(user.Profile)
	}
	return user, err
}
// 分页查询用户
func GetAllUsers(p int, size int) (u utils.Page, err error) {
	o := orm.NewOrm()
	user := new(User)
	var users []User
	qs := o.QueryTable(user)
	count, _ := qs.Limit(-1).Count()
	_, err = qs.RelatedSel().Limit(size).Offset((p - 1) * size).All(&users)
	for _, u := range users {
		if u.Profile != nil {
			err = o.Read(u.Profile)
		}
	}
	c, _ := strconv.Atoi(strconv.FormatInt(count, 10))
	return utils.Pagination(c, p, size, users), err
}
// 更新指定用户
func UpdateUser(uid int, uu *User) (a *User, err error) {
	o := orm.NewOrm()
	user := User{Id: uid}
	profile := Profile{Id: uid}
	if o.Read(&user) == nil {
		if uu.Username != "" {
			user.Username = uu.Username
		}
		if uu.Password != "" {
			user.Password = uu.Password
		}
		if o.Read(&profile) == nil {
			if uu.Profile.Age > 0 {
				profile.Age = uu.Profile.Age
			}
			if uu.Profile.Address != "" {
				profile.Address = uu.Profile.Address
			}
			if uu.Profile.Gender == 0 || uu.Profile.Gender == 1 {
				profile.Gender = uu.Profile.Gender
			}
			if uu.Profile.Email != "" {
				profile.Email = uu.Profile.Email
			}
		}
		user.Profile = &profile
		// 开启事务
		err = o.Begin()
		if _, err := o.Update(&user); err != nil {
			return nil, errors.New("修改失败")
		}
		if _, err := o.Update(&profile); err != nil {
			return nil, errors.New("修改失败")
		}
		if err != nil {
			err = o.Rollback()
		} else {
			err = o.Commit()
		}
		return &user, nil
	}
	return nil, err
}
// 删除指定用户
func DeleteUser(uid int) (b bool, err error) {
	// one2one 删除
	// 创建一个 ormer 对象
	o := orm.NewOrm()
	// 开启事务
	err = o.Begin()
	// 删除主表
	profile := Profile{Id: uid}
	_, err = o.Delete(&profile)
	if err != nil {
		// 回滚事务
		err = o.Rollback()
	}
	// 删除子表
	user := User{Id: uid}
	_, err = o.Delete(&user)
	if err != nil {
		// 回滚事务
		err = o.Rollback()
	}
	// 提交事务
	err = o.Commit()
	return b, err
}
// 注册 model
func init(){
	orm.RegisterModel(new(User), new(Profile))
}
复制代码

END

以上示例实现用户模块的增、删、改、查应用接口 API 功能开发。


有疑问加站长微信联系(非本文作者)

本文来自:掘金

感谢作者:play

查看原文:使用 orm 实现增删改查 - beego 框架使用笔记

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
1933 次点击
暂无回复
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏