mysql扩展的orm_beego orm 扩展

beegostudy是基于beego framework开发的,服务端数据存放在mysql

中,所以针对db的操作,自然离不开beego的orm工具。由于业务场景中经常需要返回一个分页

结果集(包含分页数据和数据),但是beego并没有提供,需要自行组装分页结果集,而且beego

的Paginator是侵入式的,用起来有些小不方便,于是我大刀阔斧的搞了一条基于beego orm的

查询组件。下面简单概要一下beegostudy 查询组件功能以及代码片段。

?

1. 主要文件功能概要

?

condition.go //解析各种操作原语

?

db.go ?//orm 扩展

?

generic_sql_builder.go //构建sql

?

pagination.go //分页struct

?

query.go //sql操作接口

?

sql_builder.go //sql构建接口

?

2. db?

?

```

package db

import (

"github.com/astaxie/beego/orm"

"strings"

)

?

//扩展orm 接口

type DB interface {

orm.Ormer

From(table string) *Querier

Execute(sql string, params ...interface{}) (int64, error)

}

//DB 实现struct

type db struct {

orm.Ormer

}

?

func NewDB() DB {

o := orm.NewOrm()

d := new(db)

d.Ormer = o

return d

}

?

func (d db) From(table string) *Querier {

query := NewQuery(d, NewGenericSQLBuilder())

query.From(table)

return query

}

//用于insert or update 操作(暂不支持batch操作,beego底层暂时不支持原生sql的batch操作)

func (d db) Execute(sql string, params ...interface{}) (int64, error) {

?

result, err := d.Raw(sql, params).Exec()

sql = strings.TrimLeft(sql, " ")

sql = strings.ToLower(sql)

var isInsert = strings.HasPrefix(sql, "insert")

if err != nil {

return -1, err

}

if isInsert {

return result.LastInsertId()

}else {

return result.RowsAffected()

}

}

?

?

```

2.1 query 提供jdbc操作原语

?

```

package db

import (

_ "github.com/astaxie/beego/utils/pagination"

)

?

type Querier struct {

DB

SQLBuilder

table string

}

?

func NewQuery(db DB, sqlBuilder SQLBuilder) *Querier {

q := new(Querier)

q.DB = db

q.SQLBuilder = sqlBuilder

return q

}

?

?

func (q *Querier) From(table string) *Querier {

q.table = table

q.SQLBuilder.SetTable(table)

return q

}

?

func (q *Querier) Table() string {

return q.table

}

?

func (q *Querier) GroupBy(groupBy string) *Querier {

q.SQLBuilder.GroupBy(groupBy)

return q

}

func (q *Querier) Limit(offset int, rowCount int) *Querier {

q.SQLBuilder.Limit(offset, rowCount)

return q

}

?

func (q *Querier) OrderBy(orderBy string) *Querier {

if len(orderBy) == 0 {

return q

}

q.SQLBuilder.OrderBy(orderBy)

return q

}

?

func (q *Querier) Select(columns ... string) *Querier {

q.SQLBuilder.Select(columns)

return q

}

?

func (q *Querier) Join(join string) *Querier {

q.SQLBuilder.Join(join)

return q

}

?

func (q *Querier) where(c Condition) *Querier {

sql, err := c.ToSQL(q.SQLBuilder)

if (nil == err) {

q.SQLBuilder.Where(sql, c.Params)

}

return q

}

?

func (q *Querier) Segment(sql string, params ...interface{}) *Querier {

return q.where(NewCondition(SEGMENT, sql, params))

}

?

func (q *Querier) Eq(name string, value interface{}) *Querier {

return q.where(NewCondition(EQ, name, value))

}

?

func (q *Querier) Where(name string, value interface{}) *Querier {

return q.Eq(name, value)

}

?

func (q *Querier) Not(name string, value interface{}) *Querier {

return q.where(NewCondition(NOT_EQ, name, value))

}

?

func (q *Querier) In(name string, values []interface{}) *Querier {

return q.where(NewCondition(IN, name, values))

}

?

func (q *Querier) NotIn(name string, values []interface{}) *Querier {

return q.where(NewCondition(NOT_IN, name, values))

}

func (q Querier) Between(name string, values []interface{}) *Querier {

return q.where(NewCondition(BETWEEN, name, values))

}

?

func (q *Querier) NotBetween(name string, values []interface{}) *Querier {

return q.where(NewCondition(NOT_BETWEEN, name, values))

}

?

func (q *Querier) Less(name string, value interface{}) *Querier {

return q.where(NewCondition(LESS, name, value))

}

?

func (q *Querier) LessOrEquals(name string, value interface{}) *Querier {

return q.where(NewCondition(LE, name, value))

}

?

?

func (q *Querier) Great(name string, value interface{}) *Querier {

return q.where(NewCondition(GREAT, name, value))

}

?

func (q *Querier) GreatOrEquals(name string, value interface{}) *Querier {

return q.where(NewCondition(GE, name, value))

}

?

func (q *Querier) IsNull(name string, value interface{}) *Querier {

return q.where(NewCondition(NULL, name, value))

}

?

func (q *Querier) IsNotNull(name string, value interface{}) *Querier {

return q.where(NewCondition(NOT_NULL, name, value))

}

?

func (q Querier) Like(name string, value interface{}) *Querier {

return q.where(NewCondition(LIKE, name, value))

}

?

func (q *Querier) NotLike(name string, value interface{}) *Querier {

return q.where(NewCondition(NOT_LIKE, name, value))

}

?

func (q *Querier) ToSql() string {

return q.SQLBuilder.ToSql()

}

?

?

func (q *Querier) First(container interface{}) error {

var err error

var sql = q.ToSql()

err = q.Raw(sql, q.Parameters()).QueryRow(container)

?

return err

}

//分页查询function(这才我想要的)

func (q *Querier) Pagination(container interface{}, page int, pageSize int) (*Pagination, error) {

var err error

var totalItem int

var hasNext bool

q.Limit((page - 1) * pageSize, pageSize)

q.Raw(q.ToCountSql(), q.Parameters()).QueryRow(&totalItem)

var sql = q.ToSql()

?

_, err = q.Raw(sql, q.Parameters()).QueryRows(container)

?

pagination := NewPagination(page, totalItem, hasNext)

pagination.setPerPage(pageSize)

pagination.hasNext = pagination.TotalPages() > page

pagination.SetData(container)

?

return pagination, err

}

?

```

2.2 sql_builder sql 构建组装接口

?

```

package db

?

type SQLBuilder interface {

SetTable(tableName string)

Parameters() []interface{}

ToCountSql() string

ToSql() string

Where(condition string, params ... interface{})

Select(columns []string)

ClearSelect()

Join(joinSql string)

GroupBy(groupBy string)

OrderBy(orderBy string)

Limit(offset int, rowCount int)

HasLimit() bool

EscapeColumn(column string) string

}

```

?

2.3 pagination 分页struct

?

```

package db

import (

"beego_study/utils"

"math"

"net/url"

"strconv"

)

?

const DEFAULT_PER_PAGE = 10

const MAX_SHOW_PAGE = 9

?

type Mode int

?

const (

FULL Mode = 1 + iota

NEXT_ONLY

)

?

type Pagination struct {

Page ? ? ?int

PerPage ? int

Total ? ? int

Data ? ? ?[]interface{}

hasNext ? bool

pageRange []int

url ? ? ? *url.URL

}

?

func NewPagination(page int, total int, hasNext bool) *Pagination {

pagination := new(Pagination)

?

if page <= 0 {

page = 1

}

pagination.PerPage = DEFAULT_PER_PAGE

pagination.Page = page

pagination.Total = total

pagination.hasNext = hasNext

return pagination

}

?

func (p *Pagination) setPerPage(perPage int) {

p.PerPage = perPage

}

?

func (p *Pagination) TotalPages() int {

return (p.Total + p.PerPage - 1) / p.PerPage;

}

?

func (p *Pagination) NextPage() int {

if (p.Page < p.TotalPages()) {

return p.Page + 1;

}

return -1;

}

?

func (p *Pagination) PrevPage() int {

if p.Page <= 1 {

return -1

}else {

return p.Page - 1

}

}

?

func (p *Pagination) Offset() int {

return (p.Page - 1) * p.PerPage + 1;

}

?

func ( p *Pagination) HasNext() bool {

return p.hasNext

}

?

func (p *Pagination) SetData(container interface{}) {

p.Data = utils.ToSlice(container)

}

?

//由于pc和mobile 屏幕尺寸大小不一

//可以通过maxShowPages控制分页条大小

func (p *Pagination) Pages(maxShowPages int) []int {

?

if (maxShowPages < 5 || maxShowPages > MAX_SHOW_PAGE) {

maxShowPages = MAX_SHOW_PAGE;

}

middlePageNum := maxShowPages / 2

if p.pageRange == nil && p.Total > 0 {

var pages []int

pageNums := p.TotalPages()

page := p.Page

switch {

case page >= pageNums - middlePageNum && pageNums > maxShowPages:

start := pageNums - maxShowPages + 1

pages = make([]int, maxShowPages)

for i := range pages {

pages[i] = start + i

}

case page >= (middlePageNum + 1) && pageNums > maxShowPages:

start := page - middlePageNum

pages = make([]int, int(math.Min(float64(maxShowPages), float64(page + middlePageNum + 1))))

for i := range pages {

pages[i] = start + i

}

default:

pages = make([]int, int(math.Min(float64(maxShowPages), float64(pageNums))))

for i := range pages {

pages[i] = i + 1

}

}

p.pageRange = pages

}

return p.pageRange

}

?

?

func (p *Pagination) PageLink(page int) string {

values := p.url.Query()

values.Set("page", strconv.Itoa(page))

p.url.RawQuery = values.Encode()

return p.url.String()

}

?

// Returns URL to the previous page.

func (p *Pagination) PageLinkPrev() (link string) {

if p.HasPrev() {

link = p.PageLink(p.Page - 1)

}

return

}

?

// Returns URL to the next page.

func (p *Pagination) PageLinkNext() (link string) {

if p.HasNext() {

link = p.PageLink(p.Page + 1)

}

return

}

?

// Returns URL to the first page.

func (p *Pagination) PageLinkFirst() (link string) {

return p.PageLink(1)

}

?

// Returns URL to the last page.

func (p *Pagination) PageLinkLast() (link string) {

return p.PageLink(p.TotalPages())

}

?

func ( p *Pagination) HasPrev() bool {

return p.Page > 1

}

?

func (p *Pagination) IsActive(pagea int) bool {

return p.Page == pagea

}

?

func (p *Pagination) SetUrl(url *url.URL) {

p.url = url

}

?

```

2.4 使用实例

?

```

func TestPagination(t *testing.T) {

pagination, _ := db.NewDB().From("user").Select("id", "name").Pagination(&[]entities.User{}, 1, 10)

for _, value := range pagination.Data {

fmt.Println("id", value.(entities.User).Id, "name", value.(entities.User).Name)

}

}

```

?

由于当前博客功能不完善,有问题可以发我qq:406504302

想看源码的朋友点这里[beegostudy](https://github.com/zld406504302/beego_study)

原文:http://zld406504302.iteye.com/blog/2264757

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值