Пользовательские поля в Many2Many JoinTable

#mysql #go #go-gorm

#mysql #Вперед #go-gorm

Вопрос:

У меня есть эта модель с пользовательским соединяемым столом:

 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
}
 

Как можно присвоить значение Home полю при создании нового Person ?

Ответ №1:

Способ 1

Из того, что я вижу в документах, вот простой способ, которым вы могли бы в настоящее время это сделать:

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

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

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

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

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

// Add an association with custom values
DB.Create(amp;PersonAddress{
    PersonID:  person.ID,
    AddressID: addr2.ID,
    Home:      true,
})
 

Здесь мы используем фактическую модель таблицы соединений, чтобы вставить строку с нужными нам значениями.

Мы также можем фильтровать запросы для ассоциации:

 addr := Address{}
// Query association with filters on join table
DB.Where("person_addresses.home = true").
    Model(amp;person).
    Association("Addresses").
    Find(amp;addr)
 

Способ 2

Вот более волшебный способ, используя (ab) Context для передачи значений в BeforeSave перехват, в дополнение к SetupJoinTable приведенному выше коду:

 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(amp;person).
    Association("Addresses").
    Append(amp;addr2)
 

Этот метод кажется мне неприятным, но он работает.

Ответ №2:

Поскольку вы можете найти этот пункт в официальных документах GROM, вы можете реализовать некоторые методы для каждой таблицы (структуры).

Вы можете реализовать методы beforeCreate() и / или afterCreate() для вашей таблицы соединений, gorm проверит этот метод вовремя!

Вы можете делать что угодно внутри этих методов для достижения своей цели. здесь вы найдете полную документацию.

наслаждайтесь 😉

Комментарии:

1. Я могу реализовать beforeCreate() в таблице соединений, чтобы установить переменную Home, но я не понимаю, как передать значение Home в beforeCreate() Перехват.

2. Существует метод для обработки этого, вы можете использовать этот метод и реализовать обработчик для обработки того, что вы хотите. DB.SetJoinTableHandler()

3. С внедрением JoinTableHandlerInterface вы сможете создавать свои собственные методы для применения CRUD к вашим данным. Вы можете попросить меня привести пример, если вы с этим не знакомы.