Many2Many JoinTable 中的自定义字段

Roc*_*tto 3 mysql go go-gorm

我有一个带有自定义 JoinTable 的模型:

type Person struct {
  ID        int
  Name      string
  Addresses []Address `gorm:"many2many:person_addresses;"`
}

type Address struct {
  ID   uint
  Name string
}

type PersonAddress struct {
  PersonID  int
  AddressID int
  Home      bool
  CreatedAt time.Time
  DeletedAt gorm.DeletedAt
}
Run Code Online (Sandbox Code Playgroud)

Home创建新字段时如何为该字段分配值Person

Eze*_*uns 5

方法一

从我在文档中看到的,这是您目前可以执行此操作的一种简洁方法:

DB.SetupJoinTable(&Person{}, "Addresses", &PersonAddress{})

addr1 := Address{Name: "addr1"}
DB.Create(&addr1)

addr2 := Address{Name: "addr2"}
DB.Create(&addr2)

person := Person{Name: "jinzhu"}
DB.Create(&person)

// Add an association with default values (i.e. Home = false)
DB.Model(&person).Association("Addresses").Append(&addr1)

// Add an association with custom values
DB.Create(&PersonAddress{
    PersonID:  person.ID,
    AddressID: addr2.ID,
    Home:      true,
})
Run Code Online (Sandbox Code Playgroud)

这里我们使用实际的连接表模型来插入包含我们想要的值的行。

我们还可以过滤关联查询:

addr := Address{}
// Query association with filters on join table
DB.Where("person_addresses.home = true").
    Model(&person).
    Association("Addresses").
    Find(&addr)
Run Code Online (Sandbox Code Playgroud)

方法二

除了上面的代码之外,还有一种更神奇的方法,即 (ab) 使用 将Context值传递给挂钩:BeforeSaveSetupJoinTable

func (pa *PersonAddress) BeforeSave(tx *gorm.DB) error {
    home, ok := tx.Statement.Context.Value("home").(bool)
    if ok {
        pa.Home = home
    }
    return nil
}

// ...

DB.WithContext(context.WithValue(context.Background(), "home", true)).
    Model(&person).
    Association("Addresses").
    Append(&addr2)
Run Code Online (Sandbox Code Playgroud)

这个方法我觉得很恶心,但是很有效。