GoRose

Go 语言的 ORM 框架
授权协议 MIT
开发语言 Google Go
所属分类 程序开发、 ORM/持久层框架
软件类型 开源软件
地区 国产
投 递 者 齐坚成
操作系统 跨平台
开源组织
适用人群 未知
 软件概览

gorose是一个golang orm框架, 借鉴自laravel的eloquent. gorose 2.0 采用模块化架构, 通过interface的api通信,严格的上层依赖下层.每一个模块都可以拆卸, 甚至可以自定义为自己喜欢的样子.
模块关系图如下:

 gorose-2.0-design

安装

  • go.mod
require github.com/gohouse/gorose v2.0-rc10
  • docker
docker run -it --rm ababy/gorose sh -c "go run main.go"

docker 镜像: ababy/gorose, docker镜像包含了gorose所必须的包和运行环境, 查看Dockerfile

文档

最新版2.x文档
1.x文档
0.x文档

api预览

db.Table().Fields().Where().GroupBy().Having().OrderBy().Limit().Select()
db.Table().Data().Insert()
db.Table().Data().Where().Update()
db.Table().Where().Delete()

使用建议

gorose提供数据对象绑定(map, struct), 同时支持字符串表名和map数据返回. 提供了很大的灵活性
建议优先采用数据绑定的方式来完成查询操作, 做到数据源类型可控
gorose提供了默认的 gorose.Map 和 gorose.Data 类型, 用来方便初始化绑定和data

配置和链接初始化

简单配置

var configSimple = &gorose.Config{
	Driver: "sqlite3", 
	Dsn: "./db.sqlite",
}

更多配置, 可以配置集群,甚至可以同时配置不同数据库在一个集群中, 数据库会随机选择集群的数据库来完成对应的读写操作, 其中master是写库, slave是读库, 需要自己做好主从复制, 这里只负责读写

var config = &gorose.ConfigCluster{
	Master:       []&gorose.Config{}{configSimple}
    Slave:        []&gorose.Config{}{configSimple}
    Prefix:       "pre_",
    Driver:       "sqlite3",
}

初始化使用

var engin *gorose.Engin
engin, err := Open(config)

if err != nil {
    panic(err.Error())
}

原生sql操作(增删改查), session的使用

创建用户表 users

DROP TABLE IF EXISTS "users";
CREATE TABLE "users" (
	 "uid" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
	 "name" TEXT NOT NULL,
	 "age" integer NOT NULL
);

INSERT INTO "users" VALUES (1, 'gorose', 18);
INSERT INTO "users" VALUES (2, 'goroom', 18);
INSERT INTO "users" VALUES (3, 'fizzday', 18);

定义表struct

type Users struct {
	Uid  int    `gorose:"uid"`
	Name string `gorose:"name"`
	Age  int    `gorose:"age"`
}
// 设置表名, 如果没有设置, 默认使用struct的名字
func (u *Users) TableName() string {
	return "users"
}

原生查询操作

// 这里是要绑定的结构体对象
// 如果你没有定义结构体, 则可以直接使用map, map示例
// var u = gorose.Data{}
// var u = gorose.Map{}  这两个都是可以的
var u Users
session := engin.NewSession()
// 这里Bind()是为了存放结果的, 如果你使用的是NewOrm()初始化,则可以直接使用 NewOrm().Table().Query()
err := session.Bind(&u).Query("select * from users where uid=? limit 2", 1)
fmt.Println(err)
fmt.Println(u)
fmt.Println(session.LastSql())

原生增删改操作

session.Bind(&u).Query("insert into users(name,age) values(?,?)(?,?)", "gorose",18,"fizzday",19)
session.Bind(&u).Query("update users set name=? where uid=?","gorose",1)
session.Bind(&u).Query("delete from users where uid=?", 1)

对象关系映射, orm的使用

    1. 基本链式使用
var u Users
db := engin.NewOrm()
err := db.Table(&u).Fields("name").AddFields("uid","age").Distinct().Where("uid",">",0).OrWhere("age",18).
	Group("age").Having("age>1").OrderBy("uid desc").Limit(10).Offset(1).Select()
    1. 如果不想定义struct, 又想绑定指定类型的map结果, 则可以定义map类型, 如
type user gorose.Map
// 或者 以下的type定义, 都是可以正常解析的
type user2 map[string]interface{}
type users3 []user
type users4 []map[string]string
type users5 []gorose.Map
type users6 []gorose.Data
  • 2.1 开始使用map绑定
db.Table(&user).Select()
db.Table(&users4).Limit(5).Select()

注意: 如果使用的不是slice数据结构, 则只能获取到一条数据


这里使用的 gorose.Data , 实际上就是 map[string]interface{} 类型.
而 gorose.Map, 实际上是 t.MapString 类型, 这里出现了一个 t 包, 是一个golang基本数据类型的相互转换包, 请看详细介绍 http://github.com/gohouse/t

    1. laravel的First(),Get(), 用来返回结果集
      也就是说, 你甚至可以不用传入各种绑定的struct和map, 直接传入表名, 返回两个参数, 一个是 []gorose.Map结果集, 第二个是error,看成简单粗暴
      用法就是把上边的 Select() 方法换成 Get,First 即可, 只不过, Select() 只返回一个参数
    1. orm的增删改查
db.Table(&user2).Limit(10.Select()
db.Table(&user2).Where("uid", 1).Data(gorose.Data{"name","gorose"}).Update()
db.Table(&user2).Data(gorose.Data{"name","gorose33"}).Insert()
db.Table(&user2).Data([]gorose.Data{{"name","gorose33"},"name","gorose44"}).Insert()
db.Table(&user2).Where("uid", 1).Delete()

最终sql构造器, builder构造不同数据库的sql

目前支持 mysql, sqlite3, postgres, oracle, mssql, clickhouse等符合 database/sql 接口支持的数据库驱动
这一部分, 用户基本无感知, 分理出来, 主要是为了开发者可以自由添加和修改相关驱动以达到个性化的需求

binder, 数据绑定对象

这一部分也是用户无感知的, 主要是传入的绑定对象解析和数据绑定, 同样是为了开发者个性化定制而独立出来的

模块化

gorose2.0 完全模块化, 每一个模块都封装了interface接口api, 模块间调用, 都是通过接口, 上层依赖下层

  • 主模块
    • engin
      gorose 初始化配置模块, 可以全局保存并复用
    • session
      真正操作数据库底层模块, 所有的操作, 最终都会走到这里来获取或修改数据
    • orm
      对象关系映射模块, 所有的orm操作, 都在这里完成
    • builder
      构建终极执行的sql模块, 可以构建任何数据库的sql, 但要符合database/sql包的接口
  • 子模块
    • driver
      数据库驱动模块, 被engin和builder依赖, 根据驱动来搞事情
    • binder
      结果集绑定模块, 所有的返回结果集都在这里

以上主模块, 都相对独立, 可以个性化定制和替换, 只要实现相应模块的接口即可.

最佳实践

sql

DROP TABLE IF EXISTS "users";
CREATE TABLE "users" (
	 "uid" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
	 "name" TEXT NOT NULL,
	 "age" integer NOT NULL
);

INSERT INTO "users" VALUES (1, 'gorose', 18);
INSERT INTO "users" VALUES (2, 'goroom', 18);
INSERT INTO "users" VALUES (3, 'fizzday', 18);

实战代码

package main

import (
	"fmt"
	"github.com/gohouse/gorose"
	_ "github.com/mattn/go-sqlite3"
)

type Users struct {
    Uid int64 `gorose:"uid"`
    Name string `gorose:"name"`
    Age int64 `gorose:"age"`
    Xxx interface{} `gorose:"-"` // 这个字段在orm中会忽略
}

func (u *Users) TableName() string {
	return "users"
}

var err error
var engin *gorose.Engin

func init() {
    // 全局初始化数据库,并复用
    // 这里的engin需要全局保存,可以用全局变量,也可以用单例
    // 配置&gorose.Config{}是单一数据库配置
    // 如果配置读写分离集群,则使用&gorose.ConfigCluster{}
	engin, err = gorose.Open(&gorose.Config{Driver: "sqlite3", Dsn: "./db.sqlite"})
}
func DB() gorose.IOrm {
	return engin.NewOrm()
}
func main() {
	// 这里定义一个变量db, 是为了复用db对象, 可以在最后使用 db.LastSql() 获取最后执行的sql
	// 如果不复用 db, 而是直接使用 DB(), 则会新建一个orm对象, 每一次都是全新的对象
	// 所以复用 db, 一定要在当前会话周期内
	db := DB()
	
	// 查询一条
	var u Users
	// 查询数据并绑定到 user{} 上
	err = db.Table(&u).Fields("uid,name,age").Where("age",">",0).OrderBy("uid desc").Select()
	if err!=nil {
		fmt.Println(err)
	}
	fmt.Println(u, u.Name)
	fmt.Println(db.LastSql())
	
	// 查询多条
	// 查询数据并绑定到 []Users 上, 这里复用了 db 及上下文条件参数
	// 如果不想复用,则可以使用DB()就会开启全新会话,或者使用db.Reset()
	// db.Reset()只会清除上下文参数干扰,不会更换链接,DB()则会更换链接
	var u2 []Users
	err = db.Limit(10).Offset(1).Select()
	fmt.Println(u2)
	
	// 统计数据
	var count int64
	// 这里reset清除上边查询的参数干扰, 可以统计所有数据, 如果不清楚, 则条件为上边查询的条件
	// 同时, 可以新调用 DB(), 也不会产生干扰
	count,err = db.Reset().Count()
	// 或
	count, err = DB().Table(&u).Count()
	fmt.Println(count, err)
}

高级用法

  • Chunk 数据分片 大量数据批量处理 (累积处理)

    当需要操作大量数据的时候, 一次性取出再操作, 不太合理, 就可以使用chunk方法 chunk的第一个参数是指定一次操作的数据量, 根据业务量, 取100条或者1000条都可以 chunk的第二个参数是一个回调方法, 用于书写正常的数据处理逻辑 目的是做到, 无感知处理大量数据 实现原理是, 每一次操作, 自动记录当前的操作位置, 下一次重复取数据的时候, 从当前位置开始取

     User := db.Table("users")
     User.Fields("id, name").Where("id",">",2).Chunk(2, func(data []map[string]interface{}) {
         // for _,item := range data {
         // 	   fmt.Println(item)
         // }
         fmt.Println(data)
     })
    
     // 打印结果:  
     // map[id:3 name:gorose]
     // map[id:4 name:fizzday]
     // map[id:5 name:fizz3]
     // map[id:6 name:gohouse]
     [map[id:3 name:gorose] map[name:fizzday id:4]]
     [map[id:5 name:fizz3] map[id:6 name:gohouse]]
    
  • Loop 数据分片 大量数据批量处理 (从头处理)

    类似 chunk 方法, 实现原理是, 每一次操作, 都是从头开始取数据 原因: 当我们更改数据时, 更改的结果可能作为where条件会影响我们取数据的结果,所以, 可以使用Loop

    User := db.Table("users")
    User.Fields("id, name").Where("id",">",2).Loop(2, func(data []map[string]interface{}) {
        // for _,item := range data {
        // 	   fmt.Println(item)
        // }
        // 这里执行update / delete  等操作
    })
    
  • 嵌套where

     // SELECT  * FROM users  
     //     WHERE  id > 1 
     //         and ( name = 'fizz' 
     //             or ( name = 'fizz2' 
     //                 and ( name = 'fizz3' or website like 'fizzday%')
     //                 )
     //             ) 
     //     and job = 'it' LIMIT 1
     User := db.Table("users")
     User.Where("id", ">", 1).Where(func() {
             User.Where("name", "fizz").OrWhere(func() {
                 User.Where("name", "fizz2").Where(func() {
                     User.Where("name", "fizz3").OrWhere("website", "like", "fizzday%")
                 })
             })
         }).Where("job", "it").First()
  • 简介 gorose(go orm), 一个小巧强悍的go语言数据库操作orm, 灵感来源于laravel的数据库操作orm, 也就是eloquent, php、python、ruby开发者, 都会喜欢上这个orm的操作方式, 主要是链式操作比较风骚 github https://github.com/gohouse/gorose 先睹为快 db.Table("tablename").First()

  • package main import ( "fmt" "github.com/gohouse/gorose" //import Gorose _ "github.com/go-sql-driver/mysql" //只执行github.com/go-sql-driver/mysql的init函数 "errors" "strconv

  • gorose, 最风骚的go orm, 拥有链式操作, 开箱即用, 一分钟上手等八大风骚, 让golang操作数据库成为一种享受, 妈妈再也看不到我处理数据的痛苦了, 下面就让我一一讲解gorose的风情 风骚一 : 开箱即用, 一分钟上手 db := gorose.Open("xxxxxx这里是数据库配置") // 延迟关闭数据库 defer db.Close() db.Query("sele

  • 最近迷恋上了go语言, 对go有种特别的好感. 可是, 由于之前做了很久的php开发, 刚开始用go做web开发有点不太习惯, 也许是之前的 laravel 框架的 eloquent orm过于好用, 所以, 导致了使用go做web开发的各种不适应. 于是, 想着找一个类似的orm用用, 找遍了go生态圈, 发现了很多知名的 go orm, 诸如: gorm, xorm, sqlx等, 发现没有一

  • 简介 gorose(go orm), 一个小巧强悍的go语言数据库操作orm, 灵感来源于laravel的数据库操作orm, 也就是eloquent, php、python、ruby开发者, 都会喜欢上这个orm的操作方式, 主要是链式操作比较风骚 github https://github.com/gohouse/gorose 先睹为快 db.Table("tablename").First()

  • 1. where叠加的问题:  场景:    db := connection.NewDB() Job := db.Table("job") data,_ := Job.Fields("id,name").Where("id",1).Get() #然后 data,_ = Job.Fields("id,name").Where("id",2).Get() #发现返回的data是空的,但是其实数据库里

  • gorose orm新版本(0.8.0)发布,新增连接池等特色功能 经过几个日夜, gorose群众多个成员的共同艰苦奋战, 全新版本 0.8.0 发布, 在遵循简单易用的基础之上, 做出了许多改进. gorose orm既然号称 gol orm中最风骚的orm, 这次的改进, 也是风骚范儿十足, 下面我们一起来看看改进后的特色吧: 一. 按照开源项目标准重构目录,让更多的人可以自由协作共同开发

  • gorose, 最风骚的go orm, 拥有链式操作, 开箱即用, 一分钟上手等八大风骚, 让golang操作数据库成为一种享受, 妈妈再也看不到我处理数据的痛苦了, 下面就让我一一讲解gorose的风情 风骚一 : 开箱即用, 一分钟上手 db,_ := gorose.Open("xxxxxx这里是配置文件中的数据库配置") db.Query("select * from user") //

 相关资料
  • 从戏剧!框架文档: Play2.0中没有内置的JPA实现;您可以选择任何可用的实现。例如,要使用Hibernate,只需将依赖项添加到项目中: 我的选择是什么而不是冬眠? 你认为什么最适合留言板网站? 我知道Hibernate有一点开销,对吗?

  • 本文向大家介绍什么是 ORM 框架?相关面试题,主要包含被问及什么是 ORM 框架?时的应答技巧和注意事项,需要的朋友参考一下 ORM(Object Relation Mapping)对象关系映射,是把数据库中的关系数据映射成为程序中的对象。 使用 ORM 的优点:提高了开发效率降低了开发成本、开发更简单更对象化、可移植更强。

  • ORM(Object-relational mapping),对象关系映射。 是为了解决面向对象与关系型数据库存在的不匹配问题。 ORM框架的优点: 开发效率更高 数据访问更抽象、轻便 支持面向对象封装

  • 本文向大家介绍在Python的Django框架中创建语言文件,包括了在Python的Django框架中创建语言文件的使用技巧和注意事项,需要的朋友参考一下 当你标记了翻译字符串,你就需要写出(或获取已有的)对应的语言翻译信息。 这里就是它如何工作的。 地域限制 Django不支持把你的应用本地化到一个连它自己都还没被翻译的地域。 在这种情况下,它将忽略你的翻译文件。 如果你想尝试这个并且Djang

  • 嗨,我使用Play框架2.4.3和scala版本2.11我使用放心scala支持测试路线,但我得到 经过研究,我发现Junit导致了rest assured hamcrest matcher NoSuchMethodError的问题,hamcrest 1.3 这是构建。sbt文件内容 这是异常日志 请帮助说明导致异常的原因

  • 本文向大家介绍易语言的超文本浏览框实现,包括了易语言的超文本浏览框实现的使用技巧和注意事项,需要的朋友参考一下 添加一个按钮 页面内可以点击跳转 出现错误 解决办法 实验效果

  • 问题内容: 我有一个语言代码列表(如“ en”,“ es” …),我需要用以下语言显示: 是否有任何内置API可以在Android中获取这些文件,还是我应该自己映射它们? 问题答案: 该班有一个方法,这个:作为文档说: 返回此语言环境的语言名称,本地化为 。确切的输出形式取决于此语言环境是否对应于特定的语言,脚本,国家/地区和变体。 因此,您可以像这样获得语言环境的语言名称:

  • 本文向大家介绍易语言信息框添加图标的方法,包括了易语言信息框添加图标的方法的使用技巧和注意事项,需要的朋友参考一下 易语言信息框的制作很简单,但是怎么修改信息框的图标呢?下面小编为大家解决问题 1、打开易语言,选择Windows程序窗口 2、这里只需要一个按钮就足够了,如果需要其它的可以自己添加上去。 3、双击按钮进入编程界面,我们在这里编写程序。 4、然后输入一个信息框,这里的"0"的位置就是图