gorm_generics

package module
v0.0.10 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 21, 2023 License: MIT Imports: 6 Imported by: 0

README

PoC for Go generics with GORM

Introduction

This repository represents a small PoC for using Go generics together with GORM, an Object-relational mapping library for Golang.

At this stage it emphasizes possibilities, and it is not stable implementation. In this stage, it is not meant to be used for production system.

Future development is the intention for this project, and any contribution is more than welcome.

Example

package main

import (
	"context"
	"fmt"
	"log"

	"github.com/ompluscator/gorm-generics"
	"gorm.io/driver/sqlite"
	"gorm.io/gorm"
)

// Product is a domain entity
type Product struct {
	ID          uint
	Name        string
	Weight      uint
	IsAvailable bool
}

// ProductGorm is DTO used to map Product entity to database
type ProductGorm struct {
	ID          uint   `gorm:"primaryKey;column:id"`
	Name        string `gorm:"column:name"`
	Weight      uint   `gorm:"column:weight"`
	IsAvailable bool   `gorm:"column:is_available"`
}

// ToEntity respects the gorm_generics.GormModel interface
// Creates new Entity from GORM model.
func (g ProductGorm) ToEntity() Product {
	return Product{
		ID:          g.ID,
		Name:        g.Name,
		Weight:      g.Weight,
		IsAvailable: g.IsAvailable,
	}
}

// FromEntity respects the gorm_generics.GormModel interface
// Creates new GORM model from Entity.
func (g ProductGorm) FromEntity(product Product) interface{} {
	return ProductGorm{
		ID:          product.ID,
		Name:        product.Name,
		Weight:      product.Weight,
		IsAvailable: product.IsAvailable,
	}
}

func main() {
	db, err := gorm.Open(sqlite.Open("file:test?mode=memory&cache=shared&_fk=1"), &gorm.Config{})
	if err != nil {
		log.Fatal(err)
	}

	err = db.AutoMigrate(ProductGorm{})
	if err != nil {
		log.Fatal(err)
	}

	repository := gorm_generics.NewRepository[ProductGorm, Product](db)

	ctx := context.Background()

	product := Product{
		Name:        "product1",
		Weight:      100,
		IsAvailable: true,
	}
	err = repository.Insert(ctx, &product)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Println(product)
	// Out:
	// {1 product1 100 true}

	single, err := repository.FindByID(ctx, product.ID)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(single)
	// Out:
	// {1 product1 100 true}

	err = repository.Insert(ctx, &Product{
		Name:        "product2",
		Weight:      50,
		IsAvailable: true,
	})
	if err != nil {
		log.Fatal(err)
	}

	many, err := repository.Find(ctx, gorm_generics.GreaterOrEqual("weight", 50))
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(many)
	// Out:
	// [{1 product1 100 true} {2 product2 50 true}]

	err = repository.Insert(ctx, &Product{
		Name:        "product3",
		Weight:      250,
		IsAvailable: false,
	})
	if err != nil {
		log.Fatal(err)
	}

	many, err = repository.Find(ctx, gorm_generics.GreaterOrEqual("weight", 90))
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(many)
	// Out:
	// [{1 product1 100 true} {3 product3 250 false}]

	many, err = repository.Find(ctx, gorm_generics.And(
		gorm_generics.GreaterOrEqual("weight", 90),
		gorm_generics.Equal("is_available", true)),
	)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(many)
	// Out:
	// [{1 product1 100 true}]
}

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ChunkSlice added in v0.0.4

func ChunkSlice[T any](slice []T, chunkSize int) [][]T

Types

type GormModel

type GormModel[E any] interface {
	ToEntity() E
	FromEntity(entity E) interface{}
}

type GormRepository

type GormRepository[M GormModel[E], E any] struct {
	// contains filtered or unexported fields
}

func NewRepository

func NewRepository[M GormModel[E], E any](db *gorm.DB) *GormRepository[M, E]

func (*GormRepository[M, E]) Count added in v0.0.2

func (r *GormRepository[M, E]) Count(ctx context.Context, specifications ...Specification) (i int64, err error)

func (*GormRepository[M, E]) Delete added in v0.0.4

func (r *GormRepository[M, E]) Delete(ctx context.Context, entity *E) error

func (*GormRepository[M, E]) DeleteByID added in v0.0.10

func (r *GormRepository[M, E]) DeleteByID(ctx context.Context, id any) error

func (*GormRepository[M, E]) DisablePreloadAssociations added in v0.0.6

func (r *GormRepository[M, E]) DisablePreloadAssociations() *GormRepository[M, E]

func (*GormRepository[M, E]) EnablePreloadAssociations added in v0.0.6

func (r *GormRepository[M, E]) EnablePreloadAssociations() *GormRepository[M, E]

func (*GormRepository[M, E]) Find

func (r *GormRepository[M, E]) Find(ctx context.Context, specifications ...Specification) ([]E, error)

func (*GormRepository[M, E]) FindAll added in v0.0.2

func (r *GormRepository[M, E]) FindAll(ctx context.Context) ([]E, error)

func (*GormRepository[M, E]) FindByID

func (r *GormRepository[M, E]) FindByID(ctx context.Context, id any) (E, error)

func (*GormRepository[M, E]) FindWithLimit added in v0.0.2

func (r *GormRepository[M, E]) FindWithLimit(ctx context.Context, limit int, offset int, specifications ...Specification) ([]E, error)

func (GormRepository[M, E]) GetDB added in v0.0.8

func (r GormRepository[M, E]) GetDB() *gorm.DB

func (*GormRepository[M, E]) Insert

func (r *GormRepository[M, E]) Insert(ctx context.Context, entity *E) error

func (*GormRepository[M, E]) SetPreloadAssociations added in v0.0.6

func (r *GormRepository[M, E]) SetPreloadAssociations(association bool) *GormRepository[M, E]

func (*GormRepository[M, E]) Update added in v0.0.2

func (r *GormRepository[M, E]) Update(ctx context.Context, entity *E) error

type IRepository added in v0.0.10

type IRepository[M GormModel[E], E any] interface {
	Insert(ctx context.Context, entity *E) error
	Delete(ctx context.Context, entity *E) error
	DeleteByID(ctx context.Context, id any) error
	Update(ctx context.Context, entity *E) error
	FindByID(ctx context.Context, id any) (E, error)
	Find(ctx context.Context, specifications ...Specification) ([]E, error)
	Count(ctx context.Context, specifications ...Specification) (int64, error)
	FindWithLimit(ctx context.Context, limit int, offset int, specifications ...Specification) ([]E, error)
	FindAll(ctx context.Context) ([]E, error)
}

type Specification

type Specification interface {
	GetQuery() string
	GetValues() []any
}

func And

func And(specifications ...Specification) Specification

func Equal

func Equal[T any](field string, value T) Specification

func GreaterOrEqual

func GreaterOrEqual[T comparable](field string, value T) Specification

func GreaterThan

func GreaterThan[T comparable](field string, value T) Specification

func In added in v0.0.8

func In[T any](field string, value []T) Specification

func IsNull

func IsNull(field string) Specification

func LessOrEqual

func LessOrEqual[T comparable](field string, value T) Specification

func LessThan

func LessThan[T comparable](field string, value T) Specification

func Not

func Not(specification Specification) Specification

func Or

func Or(specifications ...Specification) Specification

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL