Go ORM的封装解决方式详解
目录
- 背景
- Java的orm
- Go的orm
- 解决方式
- 初始化sql
- 连接数据库
- 插入语句
- 查询语句
- gplus工具
- 最后
背景
去年慢慢开始接触了Go语言,也在公司写了几个Go的生产项目。我是从Java转过来的。(其实也不算转,公司用啥,我用啥)在这个过程中,老是想用Java的思维写Go,在开始的一两个月,那是边写边吐槽。
丑陋的错误处理,没有流式处理,还竟然没有泛型,框架生态链不成熟,没有一家独大的类似Spring的框架。(其实现在写了快一年的Go,Go还是挺香的,哈哈)
今天,我来聊一下,我在我在写Go过程中用的最多orm框架gorm。
Java的orm
写过Java的基本都知道Mybatis,Mybatis-plus。
在Mybatis-plus中操作单表非常方便,通过QueryWrapper,对于单表的操作非常的丝滑,没有任何的思维负担。
类似下面这样:
QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.lambda().eq(User::getUsername,"zhangsan").eq(User::getAge,18); userMapper.selectList(queryWrapper);
Go的orm
这里的条件查询都需要开发手动来拼接字符串,如果项目比较大的话,就会看到漫天飞的SQL字段,维护起来非常麻烦。
var users []*User sqlResult := db.Where("username = ? and age = ?", "zhangsan", 18).Find(&users)
解决方式
写了一段时间的Go之后,实在不想每次都写这些字符串拼接了,于是我给gorm封装了一个gorm-plus。
这里我使用到了go 1.18的泛型。泛型出了这么久,也该使用上了。
其实就是把Mybatis-plus的那套语法借鉴了一下。(好吧,就是抄他的)
Mybatis-plus对于单表操作提供了非常多的CRUD操作。
我给gorm-plus 也提供了类似的操作
下面是具体用法
下载:
go get github.com/acmestack/gorm-plus
初始化sql
DROP TABLE IF EXISTS `users`; CREATE TABLE `users` ( `id` int(0) NOT NULL AUTO_INCREMENT, `username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, `age` int(0) NULL DEFAULT NULL, `phone` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, `score` int(0) NULL DEFAULT NULL, `address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, `dept` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, `created_at` datetime(0) NULL DEFAULT NULL, `updated_at` datetime(0) NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic; SET FOREIGN_KEY_CHECKS = 1;
连接数据库
var GormDb *gorm.DB func init() { dsn := "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local" var err error GormDb, err = gorm.Open(mysql.Open(dsn), &gorm.Config{ Logger: logger.Default.LogMode(logger.Info), }) if err != nil { log.Fatalln(err) } gplus.Init(GormDb) }
插入语句
user := &User{Username: "zhangsan", Password: "123456", Age: 18, Score: 100, Dept: "A部门"} result := gplus.Insert(user) fmt.Println(result.RowsAffected)
查询语句
根据id查询:
注意这里需要传入泛型User
user, resultDb := gplus.SelectById[User](1) fmt.Println(user, resultDb.RowsAffected)
根据ids查询:
var ids = []int{1,2} users, resultDb := gplus.SelectByIds[User](ids) fmt.Println(users, resultDb.RowsAffected)
条件查询:
q := gplus.NewQuery[User]() q.Eq("username", "zhangsan").Eq("age",18) users, resultDb := gplus.SelectList(q) fmt.Println(users,resultDb.RowsAffected)
对比一下Mybatis-plus写法基本一致了。
QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.lambda().eq(User::getUsername,"zhangsan").eq(User::getAge,18); userMapper.selectList(queryWrapper);
更多操作请查看:
gplus工具
其实上面的写法还是需要写数据库的字段名,如果数据库的字段名很多,我们很容易写错,导致不必要的bug 产生。
一旦名称长,非常容易误写,而且如果有字段名称修改的话,还需要全局搜索一个个地修改,比较麻烦。
Go没有提供类似Java的lambad表达式或者C#中 nameof
方式直接获取某个对象的字段名称的操作,但是我们可以通过生成代码的方式生成字段名。
所有就有了gplus,它作用就是自动识别结构体,把结构体的字段名生成出来。
下载使用:
go install github.com/acmestack/gorm-plus/cmd/gplus@latest
通过 gplus gen paths=路径
,gplus 会自动识别带有// +gplus:column=true
注释的结构体,给这个结构体生成字段。
gplus 会在输入的路径下面生成 zz_gen.column.go
文件。
例如:
在example目录下创建了了一个users.go 目录,执行 gplus gen paths=./eample
users.go
// +gplus:column=true type User struct { ID int64 Username string `gorm:"column:username"` Password string Address string Age int Phone string Score int Dept string CreatedAt time.Time UpdatedAt time.Time }
zz_gen.column.go (自动生成的)
var UserColumn = struct { ID string Username string Password string Address string Age string Phone string Score string Dept string CreatedAt string UpdatedAt string }{ ID: "id", Username: "username", Password: "password", Address: "address", Age: "age", Phone: "phone", Score: "score", Dept: "dept", CreatedAt: "created_at", UpdatedAt: "updated_at", }
其实你自己也可以手写这个文件,只不过通过工具生成更加方便而已。
有了这个文件,我们的查询就变成这样:
q := gplus.NewQuery[User]() q.Eq(UserColumn.Username, "zhangsan").Eq(UserColumn.Age,18) users, resultDb := gplus.SelectList(q) fmt.Println(users,resultDb.RowsAffected)
这样维护起来就非常方便了。
最后
更多的用法请查看github地址:https://github.com/acmestack/gorm-plus
以上就是Go ORM的封装解决方式详解的详细内容,更多关于Go ORM封装的资料请关注我们其它相关文章!