那就写一个SQL库吧

一、起因

工作中一直在使用GORM,可能是项目类型或者个人风格的原因,我自己更偏向直接写SQL(因为避免不了),因此大多数时候只用到了GORM的对象映射和钩子,而对于钩子函数,我的观点是不使用,相应的逻辑应该显式写出来(方便阅读)。

所有我希望能有一款轻量的、接近标准库database/sql的工具,可以提供对象映射和表转结构体即可,基于此,我自己动手写了esql

二、主要功能

  • 对象映射
  • 自动化事务
  • 通过命令行/函数调用,生成表对应的模型文件(暂时只支持MySQL)
  • 通过结构体获取查询字段和更新字段
  • 提供日志接口,自定义日志输出

三、安装

  • 安装命令行工具
bash 复制代码
go install github.com/cyj19/esql/cmd/esql@latest
  • 安装esql
bash 复制代码
go get -u github.com/cyj19/esql@latest

四、使用方法

  • 连接
go 复制代码
dataSource := "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8&parseTime=True&loc=Local"
db, err := esql.Open(esql.Mysql, dataSource, nil)
if err != nil {
    log.Fatal(err)
}

err = db.Ping()
if err != nil {
    log.Fatal(err)
}
  • 查询单条记录
css 复制代码
userFieldNames := esql.RawFieldNames(User{})
userFields := esql.RawQueryFields(userFieldNames)
var user User
query := fmt.Sprintf("select %s from user where id=?", userFields)
err := db.QueryRow(&user, query, 2)
if err != nil {
    log.Fatal(err)
}

log.Println(user)
  • 查询多条记录
go 复制代码
userFieldNames := esql.RawFieldNames(&User{})
userFields := esql.RawQueryFields(userFieldNames)
var rows []*User
query := fmt.Sprintf("select %s from user", userFields)
err := db.QueryRows(&rows, query)
if err != nil {
    log.Fatal(err)
}

for _, row := range rows {
    log.Printf("%+v \n", row)
}
  • 执行
css 复制代码
user := User{
    Name: "ccc",
}
query := "insert into user(`name`) values(?)"
result, err := db.Exec(query, user.Name)
if err != nil {
    log.Fatal(err)
}

id, _ := result.LastInsertId()
user.ID = int(id)

log.Println(user)
  • 自动化事务
go 复制代码
err := db.Transaction(func(tx *esql.Tx) error {
    userFieldNames := esql.RawFieldNames(User{})
    userFields := esql.RawQueryFields(userFieldNames)
    var user User
    query := fmt.Sprintf("select %s from user where id=?", userFields)
    err := tx.QueryRow(&user, query, 2)
    if err != nil {
        return err
    }

    userFieldsWithPlaceHolder :=  esql.RawUpdateFieldsWithPlaceHolder(userFieldNames, "`id`")
    query = fmt.Sprintf("update user set %s where `id`=?", userFieldsWithPlaceHolder)
    result, err := tx.Exec(query, user.Name+"1", user.Age+1,  2)
    if err != nil {
        return err
    }

    log.Println(result.RowsAffected())
    return nil

})

if err != nil {
    log.Fatal(err)
}
  • 手动事务操作
go 复制代码
// 开启事务
tx, err := db.Begin()
if err != nil {
    log.Fatal(err)
}

....
if err != nil {
    // 回滚事务
    tx.Rollback()
    return err
}


// 提交事务
tx.Commit()
  • 代码生成
    命令行工具
bash 复制代码
dev@virtual-dev:~$esql
Usage of esql:
  -db string
        the database name
  -dsn string
        the dataSource
  -ip string
        the database ip (default "127.0.0.1")
  -mode string
        the database drive (default "mysql")
  -p string
        the database password
  -path string
        the path to save file (default "./")
  -port int
        the database port (default 3306)
  -tag
        the generated structure needs to be tagged
  -u string
        the database user (default "root")


dev@virtual-dev:~$ esql -db test -u root -p 123456 -path ./model

方法调用

go 复制代码
err := db.GenStructByTable(esql.Mysql, "test", "./model", false)
if err != nil {
    log.Println(err)
}
  • 自定义日志
go 复制代码
// 实现esql.Logger
type CustomLogger struct {
}

...

// 传入自定义的日志即可
db, err := esql.Open(esql.Mysql, dataSource, &CustomLogger{})
if err != nil {
    log.Fatal(err)
}

五、总结

esql提供的curd接口和database/sql高度类似,大大降低学习成本,其次还可以通过数据库表直接生成model文件,减少重复编码。

如果这个项目对你有帮助,希望能给个start支持下,感谢感谢!

项目地址:https://github.com/cyj19/esql

相关推荐
代码老y1 小时前
ASP.NET Core 高并发万字攻防战:架构设计、性能优化与生产实践
后端·性能优化·asp.net
武子康6 小时前
Java-80 深入浅出 RPC Dubbo 动态服务降级:从雪崩防护到配置中心秒级生效
java·分布式·后端·spring·微服务·rpc·dubbo
舒一笑7 小时前
我的开源项目-PandaCoder迎来史诗级大更新啦
后端·程序员·intellij idea
@昵称不存在8 小时前
Flask input 和datalist结合
后端·python·flask
zhuyasen8 小时前
Go 分布式任务和定时任务太难?sasynq 让异步任务从未如此简单
后端·go
东林牧之8 小时前
Django+celery异步:拿来即用,可移植性高
后端·python·django
超浪的晨9 小时前
Java UDP 通信详解:从基础到实战,彻底掌握无连接网络编程
java·开发语言·后端·学习·个人开发
AntBlack9 小时前
从小不学好 ,影刀 + ddddocr 实现图片验证码认证自动化
后端·python·计算机视觉
Pomelo_刘金10 小时前
Clean Architecture 整洁架构:借一只闹钟讲明白「整洁架构」的来龙去脉
后端·架构·rust
双力臂40410 小时前
Spring Boot 单元测试进阶:JUnit5 + Mock测试与切片测试实战及覆盖率报告生成
java·spring boot·后端·单元测试