最近写后端的业务逻辑,经常踩GORM的各种坑。这篇文章目的是梳理下GORM中的关联处理(association),以及自己踩过的一些坑。
我遇到的坑们
关于Gorm多态关联
有个需求需要每次更改操作都需要对应到历史记录。为了实现这个功能,需要一张额外的records表,且这张表可以同时记录广告位和广告位分组的变更信息。如果使用简单的外键的话,一个外键不可以同时对应两张表。所以在这里,需要使用多态关联而不是外键关联。Gorm提供了对于多态关联的支持。假设我们有Cat, Dog, Toy三张表,Cat和Dog都可以拥有Toy. 使用gorm实现此关系的代码如下,
1 | type Cat struct { |
其中被拥有的数据对象(这里的Toy)将被称为Owner。这个结构体里面需要手动添加OwnerId和OwnerType。OwnerID这个属性对应的是从属对象的主键,而OwnerType则记录了被拥有对象的type。比如如果是Dog的Toy, Toy的OwnerType值就会为Dog。我们在所有者对象Cat和Dog中,只需要定义一个Toy的数组,并且声明polymorphic关键字为Owner就可以了。
当我们想进行查询时,比如想获得所有Cat对应的玩具,只需要使用
1 | var toys []*Toy |
需要注意的就是OwnerID这个属性会自动关联到对应表的primary_key,所以使用多态千万不要忘了定义primary_key。
Antomigrate的一个小坑
Gorm在automigrate时是不支持migrate primary_key的。也就是说如果一开始忘记定义主键了,后来你想通过修改表定义重新automigrate一次来修改表结构是不可行的。只能手动去数据库里加上主键。
Gorm Associations用法总结
Belongs to
belongs to是一种one-to-one connection。
例子,一个用户profile属于一个用户。默认的外键是结构体的名字+主键的名字
1 | type User struct { |
Association ForeignKey
默认情况下,gorm会用owner的主键作为外键的值。但是也可以通过association_foreignkey来指定外键的值
1 | type User struct { |
Usage
1 | db.Model(&user).Related(&profile) // user一般是外面传进来的参数,profile是用来接收的对象 |