geektutu / blog

极客兔兔的博客,Coding Coding 创建有趣的开源项目。
https://geektutu.com
Apache License 2.0
167 stars 21 forks source link

动手写ORM框架 - GeeORM第七天 数据库迁移(Migrate) | 极客兔兔 #75

Open geektutu opened 4 years ago

geektutu commented 4 years ago

https://geektutu.com/post/geeorm-day7.html

7天用 Go语言/golang 从零实现 ORM 框架 GeeORM 教程(7 days implement golang object relational mapping framework from scratch tutorial),动手写 ORM 框架,参照 gorm, xorm 的实现。结构体(struct)变更时,数据库表的字段(field)自动迁移(migrate);仅支持字段新增与删除,不支持字段类型变更。

hushui502 commented 4 years ago

期待博主下个系列,三个系列撸完还是收获不小的,尤其是第二个分布式缓存。十分感谢。

xiaoxfan commented 4 years ago

写完了 感谢博主

ppd0705 commented 4 years ago

GeeORM也跟完啦,感觉tutu的分享!从Python动态语言转过来的我,对于反射这一块还是好模糊

c-jf commented 4 years ago

博主,你前面的web框架和分布式缓存我都看完了,我虽然能看懂了,但是轮到自己想写的时候就无从下手了,完全写不出东西,不知道怎么谁是,博主可以给点建议吗

geektutu commented 4 years ago

@c-jf 这个系列每篇文章的代码量基本上在 50 - 100行左右,所以总的建议还是,先逐行照着敲,能运行,逐渐找感觉。重复个2-3遍,然后再尝试自己独立实现。

c-jf commented 4 years ago

@c-jf 这个系列每篇文章的代码量基本上在 50 - 100行左右,所以总的建议还是,先逐行照着敲,能运行,逐渐找感觉。重复个2-3遍,然后再尝试自己独立实现。

好的,谢谢博主建议,我会一如既往的支持你的

ghost commented 4 years ago

虽然还是写不出来,但是终于知道在做什么,感觉花点时间还是能写出来的

BowenXiao1999 commented 4 years ago

感觉『记录新增和查询』里实现的生成SQL字句的功能没啥用,用fmt.Sprintf生成不是更快吗?不过之后这种功能可以避免写很多重复代码。

liangjfblue commented 4 years ago

模仿着撸完,并与google/wire结合,对反射和orm的原理比较清晰了

LiRonaldo commented 3 years ago

各位大佬,包括博主,我在写orm day7的时候报了一个错误, [error] 2020/11/10 23:25:56 raw.go:62: driver: bad connection [info ] 2020/11/10 23:25:56 transcation.go:26: transcation rollback [mysql] 2020/11/10 23:25:56 packets.go:446: busy buffer [mysql] 2020/11/10 23:25:56 packets.go:427: busy buffer [error] 2020/11/10 23:25:56 transcation.go:28: driver: bad connection 我连的是mysql,报的是这个错误。当我百度之后说是Migrate方法里rows没有关掉,具体原因:tx 在执行Query()操作后,rows会维护这个数据库连接,当 tx 想再次调用当前连接进行数据库操作的时候,因为连接还没有断开,没有调用 rows.Close(),tx 无法再从连接池里获取当前连接,所以会提示 busy buffer。 我看博主的代码里也没有这方面操作,为什么我的就报错了,求解答一下,不胜感激!!!

geektutu commented 3 years ago

@BowenXiao1999 ORM 其实是想尽可能屏蔽掉数据的具体语句的,特别是兼容不同的数据库。因此常用的功能还是需要封装的。

geektutu commented 3 years ago

@LiRonaldo 写的时候没测试过 Mysql,sqlite 应该是 OK的,如果是 Mysql 可能需要一些不同的处理。如果验证成功,欢迎提 PR ~

kilosliu commented 3 years ago

@LiRonaldo 各位大佬,包括博主,我在写orm day7的时候报了一个错误, [error] 2020/11/10 23:25:56 raw.go:62: driver: bad connection [info ] 2020/11/10 23:25:56 transcation.go:26: transcation rollback [mysql] 2020/11/10 23:25:56 packets.go:446: busy buffer [mysql] 2020/11/10 23:25:56 packets.go:427: busy buffer [error] 2020/11/10 23:25:56 transcation.go:28: driver: bad connection 我连的是mysql,报的是这个错误。当我百度之后说是Migrate方法里rows没有关掉,具体原因:tx 在执行Query()操作后,rows会维护这个数据库连接,当 tx 想再次调用当前连接进行数据库操作的时候,因为连接还没有断开,没有调用 rows.Close(),tx 无法再从连接池里获取当前连接,所以会提示 busy buffer。 我看博主的代码里也没有这方面操作,为什么我的就报错了,求解答一下,不胜感激!!!

因为博主用的sqlite3,mysql的话你在 cols, _ := rows.Columns() 之后将rows关闭掉就行,像这样:

rows, _ := s.Raw("select * from User").QueryRows()
cols, _ := rows.Columns()
_ = rows.Close()

同时用mysql还有一点要注意就是go操作mysql默认不支持多条语句运行,因此运行博主的数据库迁移函数也会报语法错误,需要在数据库的url中添加multiStatements=true的选项

zagreos commented 3 years ago

@LiRonaldo 各位大佬,包括博主,我在写orm day7的时候报了一个错误, [error] 2020/11/10 23:25:56 raw.go:62: driver: bad connection [info ] 2020/11/10 23:25:56 transcation.go:26: transcation rollback [mysql] 2020/11/10 23:25:56 packets.go:446: busy buffer [mysql] 2020/11/10 23:25:56 packets.go:427: busy buffer [error] 2020/11/10 23:25:56 transcation.go:28: driver: bad connection 我连的是mysql,报的是这个错误。当我百度之后说是Migrate方法里rows没有关掉,具体原因:tx 在执行Query()操作后,rows会维护这个数据库连接,当 tx 想再次调用当前连接进行数据库操作的时候,因为连接还没有断开,没有调用 rows.Close(),tx 无法再从连接池里获取当前连接,所以会提示 busy buffer。 我看博主的代码里也没有这方面操作,为什么我的就报错了,求解答一下,不胜感激!!!

一条transaction里面的所有操作都是同步的,mysql为了保证事务的顺序执行 连接池里面只有一个连接,就像你所说的在Query()操作之后,rows获得了这个链接,你要断开这个链接,才可以继续Exec别的SQL语句。修改一下Migrate里面的方法:

valiner commented 3 years ago

完结🎉,博主牛掰。

Omari-00 commented 2 years ago

完结🎉感谢geektutu

SakuraILU commented 1 year ago

仿照着思路写了一个出来,收获颇多,感谢博主的无私奉献。感觉有两点可以改进: 一个是migrate的时候没有考虑主键,可以把原表改名,然后create一个带主键的表,把原来的表项insert into as select到新表中,最后删除原表。 另一个是创建表的时候可以支持复合主键,create table tablename(mem1 type1, mem2 type2, mem3 type3, PRIMARY KEY(men1,men2))

blkcor commented 2 months ago

厉害大佬 学到了很多