Introduction
An easy ORM tool for Golang, support MyBatis-Like XML template SQL
待完成的任务
- 重构 parser
- 对象继承的实现
- 延迟加载的实现
已知 bug
< < < <
和 MyBatis 的区别
GoBatis 就是对 MyBatis 的简单模仿。 但有下列不同
-
动态 sql 语句的格式
我实现一个和 mybatis 类似的 if, chose, foreach, trim, set 和 where 之类的 xml 基本实现,同时也支持 go template 来生成 sql。
-
自动生成 sql 语句
MyBatis 是不会自动生成 sql 语句的, 我觉得能像大部份的 orm 一样能生成 sql 的话,可以省很多工作 请见 SQL 自动生成
基本思路
- 用户定义结构和接口
- 在接口的方法上定义 sql (可以在 xml 中或方法的注释中)
- 用工具生成接口的实现
- 创建接口的实例并使用它
Roadmap
- 升级 go1.14 后 goparser 特别慢,准备用 goparser2 替换
- 将 xml 相关代码移到 xml 子目录
- 将 sql 生成工具 builder 相关代码移到 sql 子目录
Usage
注意, gobatis 也支持 xml, 请见 example_xml 目录
gobatisgo get -u -v github.com/runner-mei/GoBatis/cmd/gobatis//go:generate gobatis user.go
//go:generate gobatis user.go
package example
import (
"time"
)
type AuthUser struct {
ID int64 `json:"id"`
Username string `json:"username"`
Phone string `json:"phone"`
Address *string `json:"address"`
Status uint8 `json:"status"`
BirthDay *time.Time `json:"birth_day"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type UserDao interface {
// @postgres insert into auth_users(username, phone, address, status, birth_day, created_at, updated_at)
// values (#{username},#{phone},#{address},#{status},#{birth_day},CURRENT_TIMESTAMP, CURRENT_TIMESTAMP) returning id
//
// @default insert into auth_users(username, phone, address, status, birth_day, created_at, updated_at)
// values (#{username},#{phone},#{address},#{status},#{birth_day},CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
Insert(u *AuthUser) (int64, error)
}
go generate ./...
// Please don't edit this file!
package example
import (
"errors"
gobatis "github.com/runner-mei/GoBatis"
)
func init() {
gobatis.Init(func(ctx *gobatis.InitContext) error {
{ //// UserDao.Insert
if _, exists := ctx.Statements["UserDao.Insert"]; !exists {
sqlStr := "insert into auth_users(username, phone, address, status, birth_day, created_at, updated_at)\r\n values (#{username},#{phone},#{address},#{status},#{birth_day},CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)"
switch ctx.Dialect {
case gobatis.ToDbType("mssql"):
sqlStr = "insert into auth_users(username, phone, address, status, birth_day, created_at, updated_at)\r\n output inserted.id\r\n values (#{username},#{phone},#{address},#{status},#{birth_day},CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)"
case gobatis.ToDbType("postgres"):
sqlStr = "insert into auth_users(username, phone, address, status, birth_day, created_at, updated_at)\r\n values (#{username},#{phone},#{address},#{status},#{birth_day},CURRENT_TIMESTAMP, CURRENT_TIMESTAMP) returning id"
}
stmt, err := gobatis.NewMapppedStatement(ctx, "UserDao.Insert",
gobatis.StatementTypeInsert,
gobatis.ResultStruct,
sqlStr)
if err != nil {
return err
}
ctx.Statements["UserDao.Insert"] = stmt
}
}
})
}
func NewUserDao(session gobatis.SqlSession) UserDao {
return &UserDaoImpl{session: session}
}
type UserDaoImpl struct {
session gobatis.SqlSession
}
func (impl *UserDaoImpl) Insert(u *AuthUser) (int64, error) {
return impl.session.Insert("UserDao.Insert",
[]string{
"u",
},
[]interface{}{
u,
})
}
...
- use UserDao
factory, err := gobatis.New(&gobatis.Config{DriverName: tests.TestDrv,
DataSource: tests.TestConnURL,
// XMLPaths: []string{"example/test.xml"},
})
userDao := NewUserDao(factory.SessionReference())
id, err := userDao.Insert(&insertUser)
if err != nil {
fmt.Println(err)
return
}
fmt.Println("insert success!")
u, err := userDao.Get(id)
if err != nil {
fmt.Println(err)
return
}
fmt.Println("fetch user from database!")
_, err = userDao.Delete(id)
if err != nil {
fmt.Println(err)
return
}
fmt.Println("delete success!")
注意
GoBatis 是基于 osm 的基础上修改来的,goparser 则是在 light 的基础上修改来的, reflectx 则从 sqlx 拷贝过来的