gormrepo is the centerpiece of a complete GORM ecosystem, delivering type-safe, enterprise-grade, and quite efficient database operations to Go developers.
π Combining the best of Java MyBatis Plus + Python SQLAlchemy, designed with Go's next-generation ORM toolchain
| Ecosystem | Java MyBatis Plus | Python SQLAlchemy | Go GORM Ecosystem |
|---|---|---|---|
| Type-Safe Columns | Example::getName |
Example.name |
cls.Name.Eq() |
| Code Generation | β Plugin support | β Reflection | β AST precision |
| Repo Pattern | β BaseMapper | β Session API | β GormRepo |
| Native Language | π‘ Limited | π‘ Limited | β Complete support |
go get github.com/yyle88/gormrepotype Account struct {
ID uint `gorm:"primaryKey"`
Accountname string `gorm:"uniqueIndex" cnm:"accountname"`
Nickname string `gorm:"index" cnm:"nickname"`
Age int `cnm:"age"`
}// Auto-generated
func (*Account) Columns() *AccountColumns {
return &AccountColumns{
ID: "id",
Accountname: "accountname",
Nickname: "nickname",
Age: "age",
}
}
type AccountColumns struct {
ID gormcnm.ColumnName[uint]
Accountname gormcnm.ColumnName[string]
Nickname gormcnm.ColumnName[string]
Age gormcnm.ColumnName[int]
}repo := gormrepo.NewRepo(&Account{}, (&Account{}).Columns())// Classic GORM
err := db.Where("name = ?", "alice").First(&account).Error
// gormrepo - First
account, err := repo.With(ctx, db).First(func(db *gorm.DB, cls *AccountColumns) *gorm.DB {
return db.Where(cls.Accountname.Eq("alice"))
})
// gormrepo - FirstE (returns ErrorOrNotExist)
account, erb := repo.With(ctx, db).FirstE(func(db *gorm.DB, cls *AccountColumns) *gorm.DB {
return db.Where(cls.Accountname.Eq("alice"))
})
// gormrepo - Find
accounts, err := repo.With(ctx, db).Find(func(db *gorm.DB, cls *AccountColumns) *gorm.DB {
return db.Where(cls.Age.Gte(18))
})
// gormrepo - FindPage
accounts, err := repo.With(ctx, db).FindPage(
func(db *gorm.DB, cls *AccountColumns) *gorm.DB {
return db.Where(cls.Age.Gte(18))
},
func(cls *AccountColumns) gormcnm.OrderByBottle {
return cls.ID.OrderByBottle("DESC")
},
&gormrepo.Pagination{Limit: 10, Offset: 0},
)
// gormrepo - FindPageAndCount
accounts, count, err := repo.With(ctx, db).FindPageAndCount(
func(db *gorm.DB, cls *AccountColumns) *gorm.DB {
return db.Where(cls.Age.Between(18, 65))
},
func(cls *AccountColumns) gormcnm.OrderByBottle {
return cls.ID.OrderByBottle("DESC")
},
&gormrepo.Pagination{Limit: 10, Offset: 0},
)
// gormrepo - Count
count, err := repo.With(ctx, db).Count(func(db *gorm.DB, cls *AccountColumns) *gorm.DB {
return db.Where(cls.Age.Gte(18))
})
// gormrepo - Exist
exist, err := repo.With(ctx, db).Exist(func(db *gorm.DB, cls *AccountColumns) *gorm.DB {
return db.Where(cls.Accountname.Eq("alice"))
})
// gormrepo - Where conditions: Eq, Ne, Gt, Lt, Gte, Lte
accounts, err := repo.With(ctx, db).Find(func(db *gorm.DB, cls *AccountColumns) *gorm.DB {
return db.Where(cls.Age.Gt(18)). // age > 18
Where(cls.Age.Lt(60)). // age < 60
Where(cls.Age.Ne(30)) // age != 30
})
// gormrepo - Like / NotLike
accounts, err := repo.With(ctx, db).Find(func(db *gorm.DB, cls *AccountColumns) *gorm.DB {
return db.Where(cls.Nickname.Like("%test%")).
Where(cls.Accountname.NotLike("%admin%"))
})
// gormrepo - In / NotIn
accounts, err := repo.With(ctx, db).Find(func(db *gorm.DB, cls *AccountColumns) *gorm.DB {
return db.Where(cls.ID.In([]uint{1, 2, 3})).
Where(cls.Age.NotIn([]int{18, 19, 20}))
})
// gormrepo - Between / NotBetween
accounts, err := repo.With(ctx, db).Find(func(db *gorm.DB, cls *AccountColumns) *gorm.DB {
return db.Where(cls.Age.Between(20, 40)).
Where(cls.ID.NotBetween(100, 200))
})
// gormrepo - IsNull / IsNotNull
accounts, err := repo.With(ctx, db).Find(func(db *gorm.DB, cls *AccountColumns) *gorm.DB {
return db.Where(cls.Nickname.IsNotNull())
})
// gormrepo - Or conditions
accounts, err := repo.With(ctx, db).Find(func(db *gorm.DB, cls *AccountColumns) *gorm.DB {
return db.Where(cls.Age.Gte(18)).
Or(cls.Nickname.Eq("vip"))
})
// gormrepo - Order / Select
accounts, err := repo.With(ctx, db).Find(func(db *gorm.DB, cls *AccountColumns) *gorm.DB {
return db.Where(cls.Age.Gte(18)).
Order(cls.Age.Name() + " DESC").
Select(cls.ID.Name(), cls.Accountname.Name())
})| Method | Parameters | Returns | Description |
|---|---|---|---|
First |
where func(db *gorm.DB, cls CLS) *gorm.DB |
*MOD, error |
Find first matching record |
FirstE |
where func(db *gorm.DB, cls CLS) *gorm.DB |
*MOD, *ErrorOrNotExist |
Find first or not-exist indication |
Find |
where func(db *gorm.DB, cls CLS) *gorm.DB |
[]*MOD, error |
Find each matching records |
FindPage |
where, ordering, pagination |
[]*MOD, error |
Paginated search |
FindPageAndCount |
where, ordering, pagination |
[]*MOD, int64, error |
Paginated search with record count |
Count |
where func(db *gorm.DB, cls CLS) *gorm.DB |
int64, error |
Count matching records |
Exist |
where func(db *gorm.DB, cls CLS) *gorm.DB |
bool, error |
Check if records exist |
// Classic GORM
err := db.Create(&Account{Accountname: "bob", Nickname: "Bob", Age: 25}).Error
// gormrepo
err := repo.With(ctx, db).Create(&Account{Accountname: "bob", Nickname: "Bob", Age: 25})| Method | Parameters | Returns | Description |
|---|---|---|---|
Create |
one *MOD |
error |
Create new record |
Save |
one *MOD |
error |
Insert/update record |
// Classic GORM
err := db.Model(&Account{}).Where("id = ?", 1).Updates(map[string]interface{}{"age": 26}).Error
// gormrepo - Updates
err := repo.With(ctx, db).Updates(
func(db *gorm.DB, cls *AccountColumns) *gorm.DB {
return db.Where(cls.ID.Eq(1))
},
func(cls *AccountColumns) map[string]interface{} {
return cls.Kw(cls.Age.Kv(26)).
Kw(cls.Nickname.Kv("NewNick")).
AsMap()
},
)
// gormrepo - UpdatesM (using ColumnValueMap)
err := repo.With(ctx, db).UpdatesM(
func(db *gorm.DB, cls *AccountColumns) *gorm.DB {
return db.Where(cls.ID.Eq(1))
},
func(cls *AccountColumns) *gormcnm.ColumnValueMap {
return cls.Kw(cls.Age.Kv(26)).
Kw(cls.Nickname.Kv("NewNick"))
},
)
// gormrepo - UpdatesO (by primary key)
account := &Account{ID: 1}
err := repo.With(ctx, db).UpdatesO(account, func(cls *AccountColumns) *gormcnm.ColumnValueMap {
return cls.Kw(cls.Age.Kv(26))
})
// gormrepo - UpdatesC (combined conditions)
account := &Account{ID: 1}
err := repo.With(ctx, db).UpdatesC(account,
func(db *gorm.DB, cls *AccountColumns) *gorm.DB {
return db.Where(cls.Age.Lt(30))
},
func(cls *AccountColumns) *gormcnm.ColumnValueMap {
return cls.Kw(cls.Age.Kv(26))
},
)| Method | Parameters | Returns | Description |
|---|---|---|---|
Update |
where, valueFunc |
error |
Update single field |
Updates |
where, mapValues |
error |
Update multiple fields |
UpdatesM |
where, newValues |
error |
Update with ColumnValueMap (M=Map) |
UpdatesO |
object, newValues |
error |
Update via primary key (O=Object) |
UpdatesC |
object, where, newValues |
error |
Update with combined conditions (C=Combined) |
// Classic GORM
err := db.Where("id = ?", 1).Delete(&Account{}).Error
// gormrepo - Delete (by instance)
account := &Account{ID: 1}
err := repo.With(ctx, db).Delete(account)
// gormrepo - DeleteW (by where conditions)
err := repo.With(ctx, db).DeleteW(func(db *gorm.DB, cls *AccountColumns) *gorm.DB {
return db.Where(cls.ID.Eq(1))
})
// gormrepo - DeleteM (instance + conditions)
account := &Account{ID: 1}
err := repo.With(ctx, db).DeleteM(account, func(db *gorm.DB, cls *AccountColumns) *gorm.DB {
return db.Where(cls.Age.Lt(30))
})| Method | Parameters | Returns | Description |
|---|---|---|---|
Delete |
one *MOD |
error |
Delete record via instance |
DeleteW |
where func(db *gorm.DB, cls CLS) *gorm.DB |
error |
Delete via conditions |
DeleteM |
one *MOD, where func(db *gorm.DB, cls CLS) *gorm.DB |
error |
Delete item with conditions |
When above methods do not fit, use Invoke:
// Invoke - batch update
err := repo.With(ctx, db).Invoke(func(db *gorm.DB, cls *AccountColumns) *gorm.DB {
return db.Where(cls.Age.Gte(18)).Update(cls.Nickname.Name(), "adult")
})
// Invoke - increment field
err := repo.With(ctx, db).Invoke(func(db *gorm.DB, cls *AccountColumns) *gorm.DB {
return db.Where(cls.ID.Eq(1)).
Update(cls.Age.Name(), gorm.Expr(cls.Age.Name()+" + ?", 1))
})
// Invoke - select specific columns
var names []string
err := repo.With(ctx, db).Invoke(func(db *gorm.DB, cls *AccountColumns) *gorm.DB {
return db.Where(cls.Age.Gte(18)).Pluck(cls.Accountname.Name(), &names)
})
// Invoke - complex conditions
err := repo.With(ctx, db).Invoke(func(db *gorm.DB, cls *AccountColumns) *gorm.DB {
return db.Where(cls.Age.Between(18, 60)).
Where(cls.Nickname.IsNotNull()).
Updates(map[string]interface{}{
cls.Nickname.Name(): "active",
})
})| Method | Parameters | Returns | Description |
|---|---|---|---|
Invoke |
clsRun func(db *gorm.DB, cls CLS) *gorm.DB |
error |
Execute custom operation |
Check examples DIR with complete integration examples.
Explore the complete GORM ecosystem with these integrated packages:
- gormcnm - GORM foundation providing type-safe column queries operations
- gormcngen - Code generation engine using AST, enables type-safe GORM operations
- gormrepo - Repo pattern implementation with GORM best practices (this project)
- gormmom - Native language GORM tag generation engine with smart column naming
- gormzhcn - Complete Chinese programming interface with GORM
Each package targets different aspects of GORM development, from localization to type-safe operations and code generation.
MIT License - see LICENSE.
Contributions are welcome! Report bugs, suggest features, and contribute code:
- π Mistake reports? Open an issue on GitHub with reproduction steps
- π‘ Fresh ideas? Create an issue to discuss
- π Documentation confusing? Report it so we can improve
- π Need new features? Share the use cases to help us understand requirements
- β‘ Performance issue? Help us optimize through reporting slow operations
- π§ Configuration problem? Ask questions about complex setups
- π’ Follow project progress? Watch the repo to get new releases and features
- π Success stories? Share how this package improved the workflow
- π¬ Feedback? We welcome suggestions and comments
New code contributions, follow this process:
- Fork: Fork the repo on GitHub (using the webpage UI).
- Clone: Clone the forked project (
git clone https://github.com/yourname/repo-name.git). - Navigate: Navigate to the cloned project (
cd repo-name) - Branch: Create a feature branch (
git checkout -b feature/xxx). - Code: Implement the changes with comprehensive tests
- Testing: (Golang project) Ensure tests pass (
go test ./...) and follow Go code style conventions - Documentation: Update documentation to support client-facing changes
- Stage: Stage changes (
git add .) - Commit: Commit changes (
git commit -m "Add feature xxx") ensuring backward compatible code - Push: Push to the branch (
git push origin feature/xxx). - PR: Open a merge request on GitHub (on the GitHub webpage) with detailed description.
Please ensure tests pass and include relevant documentation updates.
Welcome to contribute to this project via submitting merge requests and reporting issues.
Project Support:
- β Give GitHub stars if this project helps you
- π€ Share with teammates and (golang) programming friends
- π Write tech blogs about development tools and workflows - we provide content writing support
- π Join the ecosystem - committed to supporting open source and the (golang) development scene
Have Fun Coding with this package! πππ