那就写一个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

相关推荐
hankeyyh7 分钟前
讲清楚Go字符串和utf8编码
后端·go
五行星辰17 分钟前
Gson修仙指南:谷歌大法的佛系JSON渡劫手册
java·后端
未完结小说22 分钟前
RabbitMQ高级(二) - MQ的可靠性
后端
Lemon12522 分钟前
LeetCode刷题常见的Java排序
后端
uhakadotcom33 分钟前
使用Python访问NVIDIA CUDA:简化并行计算
后端·面试·github
字节王德发1 小时前
如何在Springboot的Mapper中轻松添加新的SQL语句呀?
spring boot·后端·sql
Cxzzzzzzzzzz1 小时前
Supervisor的安装和使用
运维·后端·python·centos
阮瑭雅1 小时前
Bash语言的微服务
开发语言·后端·golang
uhakadotcom1 小时前
gRPC协议:高性能远程过程调用框架
后端·面试·github