SkillAgentSearch skills...

Orm

A lightweight yet powerful, fast, customizable, type-safe object-relational mapper for the Go programming language.

Install / Use

/learn @golobby/Orm
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

GoDoc CI CodeQL Go Report Card Coverage Status

Golobby ORM

GoLobby ORM is a lightweight yet powerful, fast, customizable, type-safe object-relational mapper for the Go programming language.

Table Of Contents

Introduction

GoLobby ORM is an object-relational mapper (ORM) that makes it enjoyable to interact with your database. When using Golobby ORM, each database table has a corresponding "Entity" to interact with that table using elegant APIs.

Features

  • Elegant and easy-to-use APIs with the help of Generics.
  • Type-safety.
  • Using reflection at startup to be fast during runtime.
  • No code generation!
  • Query builder for various query types.
  • Binding query results to entities.
  • Supports different kinds of relationship/Association types:
    • One to one
    • One to Many
    • Many to Many

Performance

You can run performance benchmark against GORM using

make bench

here are results from my laptop

goos: darwin
goarch: arm64
pkg: github.com/golobby/orm/benchmark
BenchmarkGolobby
BenchmarkGolobby-8        235956              4992 ns/op            2192 B/op         66 allocs/op
BenchmarkGorm
BenchmarkGorm-8            54498             21308 ns/op            7208 B/op        147 allocs/op
PASS
ok      github.com/golobby/orm/benchmark        3.118s

Quick Start

The following example demonstrates how to use the GoLobby ORM.

package main

import "github.com/golobby/orm"

// User entity
type User struct {
  ID        int64
  FirstName string
  LastName  string
  Email     string
  orm.Timestamps
}

// It will be called by ORM to setup entity.
func (u User) ConfigureEntity(e *orm.EntityConfigurator) {
    // Specify related database table for the entity.
    e.Table("users")
}

func main() {
  // Setup ORM
  err := orm.Initialize(orm.ConnectionConfig{
    // Name:          "default",  // Optional. Specify connection names if you have more than on database.
    Driver:           "sqlite3",  // Database type. Currently supported sqlite3, mysql, mariadb, postgresql. 
    ConnectionString: ":memory:", // Database DSN.
    DatabaseValidations: true,    // Validates your database tables and each table schema
  })
  
  if err != nil {
	  panic(err)
  }
  
  // Find user by primary key (ID)
  user, err := orm.Find[User](1)
  
  // Update entity
  user.Email = "jack@mail.com"
  
  // Save entity
  orm.Save(&user)
}

Creating a new Entity

Let's create a new Entity to represent User in our application.

package main

import "github.com/golobby/orm"

type User struct {
  ID       int64
  Name     string
  LastName string
  Email    string
  orm.Timestamps
}

func (u User) ConfigureEntity(e *orm.EntityConfigurator) {
    e.Table("users").
      Connection("default") // You can omit connection name if you only have one.
	
}

As you see, our user entity is nothing else than a simple struct and two methods. Entities in GoLobby ORM are implementations of Entity interface, which defines two methods:

  • ConfigureEntity: configures table, fields, and also relations to other entities.

Conventions

We have standard conventions and we encourage you to follow, but if you want to change them for any reason you can use Field method to customize how ORM inferres meta data from your Entity.

Column names

GoLobby ORM for each struct field(except slice, arrays, maps, and other nested structs) assumes a respective column named using snake case syntax. If you want a custom column name, you should specify it in ConfigureEntity method using Field() method.

package main

type User struct {
  Name string
}

func (u User) ConfigureEntity(e *orm.EntityConfigurator) {
    e.Field("Name").ColumnName("custom_name_for_column")

    e.Table("users")
}
Timestamps

for having created_at, updated_at, deleted_at timestamps in your entities you can embed orm.Timestamps struct in your entity,

type User struct {
  ID       int64
  Name     string
  LastName string
  Email    string
  orm.Timestamps
}

Also, if you want custom names for them, you can do it like this.

type User struct {
    ID       int64
    Name     string
    LastName string
    Email    string
    MyCreatedAt sql.NullTime
    MyUpdatedAt sql.NullTime
    MyDeletedAt sql.NullTime
}
func (u User) ConfigureEntity(e *orm.EntityConfigurator) {
    e.Field("MyCreatedAt").IsCreatedAt() // this will make ORM to use MyCreatedAt as created_at column
    e.Field("MyUpdatedAt").IsUpdatedAt() // this will make ORM to use MyUpdatedAt as updated_at column
    e.Field("MyDeletedAt").IsDeletedAt() // this will make ORM to use MyDeletedAt as deleted_at column

    e.Table("users")
}

As always you use Field method for configuring how ORM behaves to your struct field.

Primary Key

GoLobby ORM assumes that each entity has a primary key named id; if you want a custom primary key called, you need to specify it in entity struct.

package main

type User struct {
	PK int64
}
func (u User) ConfigureEntity(e *orm.EntityConfigurator) {
    e.Field("PK").IsPrimaryKey() // this will make ORM use PK field as primary key.
    e.Table("users")
}

Initializing ORM

After creating our entities, we need to initialize GoLobby ORM.

package main

import "github.com/golobby/orm"

func main() {
  orm.Initialize(orm.ConnectionConfig{
    // Name:             "default", You should specify connection name if you have multiple connections
    Driver:           "sqlite3",
    ConnectionString: ":memory:",
  })
}

After this step, we can start using ORM.

Fetching an entity from a database

GoLobby ORM makes it trivial to fetch entities from a database using its primary key.

user, err := orm.Find[User](1)

orm.Find is a generic function that takes a generic parameter that specifies the type of Entity we want to query and its primary key value. You can also use custom queries to get entities from the database.


user, err := orm.Query[User]().Where("id", 1).First()
user, err := orm.Query[User]().WherePK(1).First()

GoLobby ORM contains a powerful query builder, which you can use to build Select, Update, and Delete queries, but if you want to write a raw SQL query, you can.

users, err := orm.QueryRaw[User](`SELECT * FROM users`)

Saving entities or Insert/Update

GoLobby ORM makes it easy to persist an Entity to the database using Save method, it's an UPSERT method, if the primary key field is not zero inside the entity it will go for an update query; otherwise, it goes for the insert.

// this will insert entity into the table
err := orm.Save(&User{Name: "Amirreza"}) // INSERT INTO users (name) VALUES (?) , "Amirreza"
// this will update entity with id = 1
orm.Save(&User{ID: 1, Name: "Amirreza2"}) // UPDATE users SET name=? WHERE id=?, "Amirreza2", 1

Also, you can do custom update queries using query builder or raw SQL again as well.

res, err := orm.Query[User]().Where("id", 1).Update(orm.KV{"name": "amirreza2"})

Using raw SQL

_, affected, err := orm.ExecRaw[User](`UPDATE users SET name=? WHERE id=?`, "amirreza", 1)

Deleting entities

It is also easy to delete entities from a database.

err := orm.Delete(user)

You can also use query builder or raw SQL.

_, affected, err := orm.Query[Post]().WherePK(1).Delete()

_, affected, err := orm.Query[Post]().Where("id", 1).Delete()

_, affected, err := orm.ExecRaw[Post](`DELETE FROM posts WHERE id=?`, 1)

Relationships

GoLobby ORM makes it easy to have entities that have relationships with each other. Configuring relations is using ConfigureEntity method, as you will see.

HasMany

type Post struct {}

func (p Post) ConfigureEntity(e *orm.EntityConfigurator) {
    e.Table("posts").HasMany(&Comment{}, orm.HasManyConfig{})
}

As you can see, we are defining a Post entity t

View on GitHub
GitHub Stars162
CategoryData
Updated4mo ago
Forks6

Languages

Go

Security Score

97/100

Audited on Nov 22, 2025

No findings