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

相关推荐
用户479492835691515 分钟前
专升本前端毕业 1 年,从初创到大厂,我的开源项目上了 github trending,顺便聊聊做开源的收获
前端·后端·github
小小放舟、34 分钟前
PaiCLI-Demo:从零实现 ReAct Agent + Tool Call
java·后端·intellij-idea·springboot·agent·react·tool call
用户6757049885021 小时前
别再乱用了!var arr []int 和 arr := []int{} 给整懵了?不就声明个空数组,项目居然崩了?
后端·go
马达拉1 小时前
为什么Bun查询数据库接口响应比Rust还快
后端
geovindu2 小时前
go: Enumeration Algorithm
开发语言·后端·算法·golang·枚举算法
雪隐2 小时前
个人电脑玩AI-10让5060 Ti给你打工——ComfyUI,我差点被它劝退三次
人工智能·后端
工具派2 小时前
写代码时,我把这个本地 AI Commit Message 生成器接进了工作流
前端·后端
犀利豆2 小时前
AI 时代使用 Obsidian 作为 IDE
人工智能·后端
用户7917286761973 小时前
在 opencode 中使用 opencode-plugin-loop 插件完全指南
后端
用户3126874877203 小时前
MyBatis-Plus 动态分表实战:基于 DynamicTableNameInnerInterceptor 的多端数据隔离方案
后端