/gojen

Go SQL to struct generator / lightweight ORM tool

Primary LanguageGo

🍅 Gojen

Lightweight SQL to struct generator / ORM toolkit for Golang

Default template uses Goje as a helper dependency.

Steps

  1. Database → Go struct:

    • init configs gojen init or rename config.gojen.yaml.sampleconfig.gojen.yaml
    • run gojen to build database models from target database
  2. Use generated Go structs in your project.

Install Gojen (Generator command line tool)

go install github.com/mahmoud-eskandari/gojen@v0.1.1

Supported Databases

  • MySQL
  • PostgreSQL in progress

Example of using a generated model

package main

import (
	"context"
	"errors"
	"fmt"
	"log"
	"time"
	"github.com/mahmoud-eskandari/goje"
	models "__PATH_TO_MODELS_DIR__"
)

func init(){
	//init a database connection
	err := goje.InitDB(&goje.DBConfig{
		Driver:      "mysql",
		Host:        "127.0.0.1",
		Port:        3306,
		User:        "root",
		Password:    "***",
		Schema:      "mydb",
		MaxIdleTime: time.Second * 30,
	})

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

func main() {
	//pass a ctx to get a handler
  	//you should have repeat this command every time in controller
	handler := goje.MakeHandler(context.Background()) // or for begin transactions use goje.MakeTxHandler

	//models package and `User` struct... generated in previous stage from database
	//some of functions/methods that generated by gojen:

	user := models.User{
		Name:   "Mahmoud",
		Status: 1,
		Mobile: "+98912123456",
	}

	//we should pass handler because user object hasn't context handler
	//If a primary key is set, it executes an UPDATE query.
	//Otherwise, if the user object does not yet have a primary key, it runs an INSERT query.
	err = user.Save(handler)

	if err != nil {
		log.Print(err)
	} else {
		log.Printf("user saved with id: %d", user.Id)
	}

	//also we can attach context with SetCtx
	//user.SetCtx(handler)

	//change some props...
	user.Balance = 10000
	//If our object already possesses a handler, passing it again is unnecessary.
	user.Update(nil) //or user.Save(nil)

	//some of helper methods:

	//load user addresses relation with a limit and order
	user.LoadUserAddressesByUserId(goje.Limit(10), goje.Order("id DESC"))

	//get list of user by query
	users, err := models.GetUsers(handler, goje.Where("name LIKE ?", "Mahmoud"), goje.WhereIn("id IN(?)", 1, 2, 3, 100))
	if err != nil {
		log.Print(err)
	} else {
		userList := models.UserList(*users)

		//delete a list
		userList.DeleteAll(handler)
	}

	//Triggers
	models.BeforeDeleteUser = func(ch *goje.ContextHandler, u *models.User) error {
		if u.Id == 100 {
			return errors.New("you are unable to delete user(id=100) because of this trigger :)")
		}
		return nil
	}
	models.AfterDeleteUser = func(ch *goje.ContextHandler, u *models.User) {
		log.Printf("the user(%+v) has been deleted", u)
	}
	// After/Before Update etc.

	//delete user
	user.Delete(nil)

	//some of helper functions
	models.GetUserById(handler, 100)

	//counter function
	countUsers, err := models.CountUsers(handler)
	fmt.Printf("Count users(%d) %+v", countUsers, err)

	//counters with query
	countUsers, err = models.CountUsers(handler, goje.Where("status=?", 1))
	fmt.Printf("Count active users(%d) %+v", countUsers, err)
}