gom

package module
v0.1.12 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 30, 2020 License: Apache-2.0 Imports: 10 Imported by: 0

README

gom

golang的简单易用ORM工具

目标

这个ORM工具希望达到的目标

  1. 配置接入简单,易维护
  2. SQL完全可控
  3. 数据库查询结果和内存对象自动映射
  4. 学习成本低

使用方式

1.建表
create table if not exists user (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `name` varchar(32) NOT NULL,
    `age` varchar(32) NOT NULL,
    `create_time` timestamp NOT NULL,
    PRIMARY KEY (`id`),
    UNIQUE KEY `name` (`name`)
)
2.创建yaml配置
abbreviation:
  table: user
  colum: id, name, age, create_time
query:
  - name: queryById
    sql: select <colum> from <table> where id = ${id}
  - name: queryByName
    sql: select <colum> from <table> where name = ${name}
  - name: queryByAgeGT
    sql: select <colum> from <table> where age > ${age}
  - name: queryAll
    sql: select <colum> from <table>
exec:
  - name: insert
    sql: insert into <table> <colum> values (default, ${name}, ${age), Now()})

query字段里面都是select查询语句

exec里面是更新和删除语句.

query和exec中的name将在golang代码中使用,在单个yaml文件里面name需要是唯一的.

abbreviation定义的是重复使用的片段, 在sql中出现的<key>都会自动替换成abbreviation中定义的值

select <colum> from <table>会被替换为 select id, name, age, create_time from user.

3.在代码中加载yaml
const (
	DBUser     = "root"
	DBPassword = "11111111"
	DBIP       = "127.0.0.1"
	DBPort     = "3306"
	Database   = "test"
	DBOptions  = "charset=utf8mb4&parseTime=True&loc=Local"
)

type User struct {
	ID          int64
	Name        string
	Age         int
	CreateTime  time.Time
}

func (u *User) Scan(scanable Scanable) error {
	return scanable.Scan(&u.ID, &u.Name, &u.Age, &u.CreateTime)
}

m, err := LoadModel("model_test.yaml", &User{})
if err != nil {
    // error 处理
}

DBURL := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?%s", DBUser, DBPassword, DBIP, DBPort, Database, DBOptions)
db, err := sql.Open("mysql", DBURL)
if err != nil {
    // 创建数据库连接失败
}

定义User结构, 加载yaml文件, 创建数据库连接.

这里要注意,User必须实现Scan方法, Scan方法的参数顺序和select出来的字段顺序必须一致

4.使用yaml中的sql
1| users, err := m.Query(db, "queryAll")  
 
2| user, err := m.QueryRow(db, "queryById", 1)
3| user, err := m.QueryRow(db, "queryById", User{ID:1})
4| user, err := m.QueryRow(db, "queryById", &User{ID:1})

5| users, err := m.Query(db, "queryByAgeGT", 10)
6| users, err := m.Query(db, "queryByAgeGT", User{Age:10})
7| users, err := m.Query(db, "queryByAgeGT", &User{Age:10})
 
8| AffectRows, LastInsertID, err = m.Exec(db, "insert", "bob", 35)
9| AffectRows, LastInsertID, err = m.Exec(db, "insert", &User{Name:"bob", Age:35})

QueryRow查询一条结果

Query查询结果列表

Exec执行插入,更新,删除操作

参数类型支持结构指针(4,7,9行),结构(3,6行)和变长的基础数据类型(2,5,8行).

看个例子

name: queryComplicate
sql: select <column> from <table> where Name = ${name} and Age = ${age}"
  • 如果是指针或结构,参数绑定规则可以参考下例:

    m.Query(db, "queryComplicate", &User{Name:"bob", Age:35})

    ${name}会在User中找到Name字段,${age}则会绑定到User中的Age字段.

  • 如果调用方式是用变长的基础数据类型:

    m.Query(db, "queryComplicate", "bob", 35)

    ${name}将绑定第一个参数"bob", ${age}绑定第二个参数35, 此时函数参数顺序非常重要

5.批量插入

go的sql dirver不支持批量插入,gom对此做了增强,一个批量插入例子如下:

func getMockUserList() []*User {
	return []*User{
        &User{Name: "admin", Age: 10},
        &User{Name: "Aabbye", Age: 10},
        &User{Name: "Cadence", Age: 10},
        &User{Name: "Galen", Age: 10},
        &User{Name: "Adams", Age: 10},
	}
}

n, id, err := m.MultiInsert(db, "insert", getMockUserList(), 2)
if err != nil {
    t.Error("insert data failed!", err)
} else {
    t.Logf("multi insert %d rows, last insert id is %d", n, id)
}

MultiInsert执行批量插入操作,最后参数2是每批插入数据.

上例中sql是 insert into ... values (xx, xx, xx, xx), 插入数据有5条, 分批插入,每批2条数据, 实际执行情况如下表

批次 sql 插入参数
第1批 insert into ... values (xx, xx, xx, xx), (xx, xx, xx, xx) user[0], user[1]
第2批 insert into ... values (xx, xx, xx, xx), (xx, xx, xx, xx) user[2], user[3]
第3批 insert into ... values (xx, xx, xx, xx) user[4]

sql的扩展是自动的, values后面的括号内容将按一批插入数量复制N-1份.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var DefaultOrm = NewOrm()

Functions

func AddYamlPaths added in v0.1.3

func AddYamlPaths(paths ...string)

AddYamlPaths add path for search yaml

func ToMultiObjs added in v0.1.11

func ToMultiObjs(rows *sql.Rows, temp interface{}) ([]any, error)

func ToMultiObjsByType added in v0.1.11

func ToMultiObjsByType(rows *sql.Rows, tp reflect.Type) ([]any, error)

func ToObj added in v0.1.11

func ToObj(row *sql.Row, temp interface{}) (any, error)

func ToObjByType added in v0.1.11

func ToObjByType(row *sql.Row, tp reflect.Type) (any, error)

Types

type Model

type Model interface {
	Exec(c SQLConn, name string, args ...any) (int64, int64, error)
	MultiInsert(c SQLConn, name string, slice any, batchSize int) (int64, int64, error)
	QueryRow(c SQLConn, name string, args ...any) (any, error)
	Query(c SQLConn, name string, args ...any) ([]any, error)
}

func LoadModel

func LoadModel(file string, v any) (Model, error)

LoadModel ...

type Orm added in v0.1.10

type Orm interface {
	ToObj(*sql.Row, interface{}) (any, error)
	ToMultiObjs(*sql.Rows, interface{}) ([]any, error)

	ToObjByType(*sql.Row, reflect.Type) (any, error)
	ToMultiObjsByType(*sql.Rows, reflect.Type) ([]any, error)
}

func NewOrm added in v0.1.10

func NewOrm() Orm

type SQLConn

type SQLConn interface {
	Exec(query string, args ...any) (sql.Result, error)
	QueryRow(query string, args ...any) *sql.Row
	Query(query string, args ...any) (*sql.Rows, error)
}

type Scanable

type Scanable interface {
	Scan(dest ...interface{}) error
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL