Skip to content
Generic Repository

Generic Repository

Overview

The Repository[T] interface is the primary data access API. It’s parameterized with Go generics for compile-time type safety — every operation returns the concrete type, not interface{}.

Creating Repositories

// From the provider registry (recommended)
userRepo := gpagorm.GetRepository[User]()
postRepo := gpagorm.GetRepository[Post]()

// From a specific provider instance
provider := gpa.MustGet[*gpagorm.Provider]("primary")
userRepo := gpagorm.GetRepository[User](provider)

CRUD Operations

Create

user := &User{Name: "John", Email: "john@example.com"}
err := userRepo.Create(ctx, user)
// user.ID is now populated

Create Batch

users := []*User{
    {Name: "Alice"},
    {Name: "Bob"},
}
err := userRepo.CreateBatch(ctx, users)

Find By ID

user, err := userRepo.FindByID(ctx, 1)
// user is *User, not interface{}

Find All

users, err := userRepo.FindAll(ctx)
// users is []*User

Update

user.Name = "Jane"
err := userRepo.Update(ctx, user)

Partial Update

err := userRepo.UpdatePartial(ctx, 1, map[string]interface{}{
    "status": "inactive",
    "age":    31,
})

Delete

err := userRepo.Delete(ctx, 1)

Delete by Condition

err := userRepo.DeleteByCondition(ctx, gpa.Where("status", gpa.OpEqual, "inactive"))

Query Operations

// Find with conditions
users, err := userRepo.Query(ctx,
    gpa.Where("age", gpa.OpGreaterThan, 18),
    gpa.Where("status", gpa.OpEqual, "active"),
)

// Find single result
user, err := userRepo.QueryOne(ctx,
    gpa.Where("email", gpa.OpEqual, "user@example.com"),
)

// Count
count, err := userRepo.Count(ctx, gpa.Where("active", gpa.OpEqual, true))

// Check existence
exists, err := userRepo.Exists(ctx, gpa.Where("email", gpa.OpEqual, "user@example.com"))

Repository Interface

type Repository[T any] interface {
    // Basic CRUD
    Create(ctx context.Context, entity *T) error
    CreateBatch(ctx context.Context, entities []*T) error
    FindByID(ctx context.Context, id interface{}) (*T, error)
    FindAll(ctx context.Context, opts ...QueryOption) ([]*T, error)
    Update(ctx context.Context, entity *T) error
    UpdatePartial(ctx context.Context, id interface{}, updates map[string]interface{}) error
    Delete(ctx context.Context, id interface{}) error
    DeleteByCondition(ctx context.Context, condition Condition) error

    // Query
    Query(ctx context.Context, opts ...QueryOption) ([]*T, error)
    QueryOne(ctx context.Context, opts ...QueryOption) (*T, error)
    Count(ctx context.Context, opts ...QueryOption) (int64, error)
    Exists(ctx context.Context, opts ...QueryOption) (bool, error)

    // Advanced
    Transaction(ctx context.Context, fn TransactionFunc[T]) error
    RawQuery(ctx context.Context, query string, args []interface{}) ([]*T, error)
    RawExec(ctx context.Context, query string, args []interface{}) (Result, error)

    // Metadata
    GetEntityInfo() (*EntityInfo, error)
    Close() error
}

SQL-Specific Repositories

SQL providers support additional operations through specialized interfaces:

SQLRepository[T]

type SQLRepository[T any] interface {
    Repository[T]
    FindBySQL(ctx, sql string, args []interface{}) ([]*T, error)
    ExecSQL(ctx, sql string, args ...interface{}) (Result, error)
    FindWithRelations(ctx, relations []string, opts ...QueryOption) ([]*T, error)
    FindByIDWithRelations(ctx, id interface{}, relations []string) (*T, error)
    CreateTable(ctx) error
    DropTable(ctx) error
    CreateIndex(ctx, fields []string, unique bool) error
    DropIndex(ctx, indexName string) error
}

MigratableRepository[T]

type MigratableRepository[T any] interface {
    SQLRepository[T]
    MigrateTable(ctx) error
    GetMigrationStatus(ctx) (MigrationStatus, error)
    GetTableInfo(ctx) (TableInfo, error)
}

KV-Specific Repositories

Redis and other key-value stores use specialized interfaces:

// Basic KV operations
type BasicKeyValueRepository[T any] interface {
    Get(ctx, key) (*T, error)
    Set(ctx, key, value *T) error
    DeleteKey(ctx, key) error
    KeyExists(ctx, key) (bool, error)
}

// TTL support
type TTLKeyValueRepository[T any] interface {
    SetWithTTL(ctx, key, value, ttl) error
    TTL(ctx, key) (time.Duration, error)
    SetTTL(ctx, key, ttl) error
    RemoveTTL(ctx, key) error
}

Document-Specific Repositories

MongoDB and other document databases:

type DocumentRepository[T any] interface {
    Repository[T]
    FindByDocument(ctx, doc map[string]interface{}) ([]*T, error)
    TextSearch(ctx, query string, opts ...QueryOption) ([]*T, error)
    FindNear(ctx, field string, point []float64, maxDistance float64) ([]*T, error)
    Aggregate(ctx, pipeline []map[string]interface{}) ([]map[string]interface{}, error)
    CreateCollection(ctx) error
    DropCollection(ctx) error
}