一、起因
工作中一直在使用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支持下,感谢感谢!