DB Relations
Enterprise supports three primary database relation types: Many-to-Many, Many-to-One, and One-to-Many. These relations are declared inside the schema files using the models relationship helpers, and the generator produces type-safe loading and association methods.
Many to Many
A Many-to-Many relationship connects two tables via a join table. For example, an Account can belong to multiple Group models, and a Group can contain multiple Account models.
Use models.ManyToMany to declare this in your schema files:
// models.ManyToMany(targetTable, sourceForeignKey, targetForeignKey, targetPrimaryKey, joinTableName)
models.ManyToMany("Group", "account_id", "group_id", "id", "account_group")
account Schema Definition db_models/account.go
package db_models
import (
"github.com/MrSametBurgazoglu/enterprise/models"
"github.com/google/uuid"
)
func Account() *models.Table {
idField := models.UUIDField("ID").DefaultFunc(uuid.New)
tb := &models.Table{
Fields: []models.FieldI{
idField,
models.StringField("Name"),
models.StringField("Surname"),
},
Relations: []*models.Relation{
models.ManyToMany("Group", "account_id", "group_id", "id", "account_group"),
},
}
tb.SetTableName("account")
tb.SetIDField(idField)
return tb
}
group Schema Definition db_models/group.go
package db_models
import (
"github.com/MrSametBurgazoglu/enterprise/models"
"github.com/google/uuid"
)
func Group() *models.Table {
idField := models.UUIDField("ID").DefaultFunc(uuid.New)
tb := &models.Table{
Fields: []models.FieldI{
idField,
models.StringField("Name"),
},
Relations: []*models.Relation{
models.ManyToMany("Account", "group_id", "account_id", "id", "account_group"),
},
}
tb.SetTableName("group")
tb.SetIDField(idField)
return tb
}
Generated Many-to-Many Methods
For Many-to-Many relations, Enterprise generates helper methods to manage row links in the join table:
// On Account model
func (t *Account) AddIntoGroup(relationship *Group) error
func (t *Account) RemoveFromGroup(relationship *Group) error
func (t *Account) IsInGroup(relationship *Group) (bool, error)
// On Group model
func (t *Group) AddIntoAccount(relationship *Account) error
func (t *Group) RemoveFromAccount(relationship *Account) error
func (t *Group) IsInAccount(relationship *Account) (bool, error)
Many to One & One to Many
A Many-to-One / One-to-Many relationship links one table to another via a foreign key on the source table. For example, an Account belongs to a Deneme (Many-to-One), and a Deneme has many Account records (One-to-Many).
models.ManyToOne: Used on the table containing the foreign key.models.OneToMany: Used on the target table.
account Schema Definition (Many-to-One)
// models.ManyToOne(targetTable, targetPrimaryKey, sourceForeignKey)
models.ManyToOne("Deneme", "id", "deneme_id")
deneme Schema Definition (One-to-Many)
// models.OneToMany(targetTable, sourcePrimaryKey, targetForeignKey)
models.OneToMany("Account", "id", "deneme_id")
Generated Relation Loading & Eager Filtering
For loading relations, Enterprise generates eager loading methods. You can pass inline callback functions to filter the loaded relation rows with a single SQL query.
account := models.NewAccount(ctx, db)
account.Where(account.IsIDEqual(targetID))
// Eagerly load the related Deneme model, filtering it inline
account.WithDeneme(func(d *models.Deneme) {
d.Where(d.IsActiveEqual(true))
})
err = account.Get()
if err == nil {
// Access the loaded relation
if account.Deneme != nil {
fmt.Println("Deneme Count:", account.Deneme.GetCount())
}
}
Similarly, you can load a list of related records:
deneme := models.NewDeneme(ctx, db)
deneme.Where(deneme.IsIDEqual(denemeID))
// Eagerly load the related accounts list
deneme.WithAccountList(func(al *models.AccountList) {
al.Where(al.IsSurnameEqual("Smith"))
})
err = deneme.Get()
if err == nil {
for _, acc := range deneme.AccountList.Items {
fmt.Println("Related Account Name:", acc.GetName())
}
}