GDAO: A Streamlined Go Persistence Framework with Enhanced Productivity and Performance

GDAO —— Go Persistence Framework

A Streamlined Go Persistence Framework with Enhanced Productivity and Performance
Combining the Abstraction of Hibernate with the Flexibility of MyBatis for Go Applications

Introduction

Gdao is an innovative persistence layer solution aimed at reducing coding workload, improving productivity, enhancing performance, supporting multi-data source integration, and facilitating data read-write separation. By leveraging Gdao, developers can decrease the amount of code required for the persistence layer by 30% to 50%, establish unified coding standards, minimize errors, and ensure easier maintenance and expansion.

gdao for go is equivalent to hibernate+mybatis for java, the gdao framework combines the abstraction of Hibernate and the flexibility of MyBatis, and solves the pain points of their respective long-standing use on ORM frameworks. Refer to the jdao usage documentation for pain points between hibernate and mybatis

  • The GDAO design structure is both concise and rigorous, with all interfaces and functions named descriptively so their purpose is immediately clear.
  • Even if you are new to GDAO, you can quickly understand its code and the associated data behaviors.
  • The simplicity of GDAO ensures that you can master its usage within minutes.

Github

Official Website

Documentation

Demo

Key Features

  1. Code Generation: Use the Gdao code generation tool to create standardized entity classes for database tables, similar to Thrift/Protobuf.
  2. Efficient Serialization: The standardized entity classes for tables implement efficient serialization and deserialization, higher performance and smaller data volume.
  3. Support for Data Read-Write Separation: Gdao supports binding multiple data sources and data read-write separation, allowing data sources to be bound to tables, classes, mapping interfaces, and other properties.
  4. Support for Data Caching: Gdao supports data caching with detailed control over cache data lifecycle and recycling features.
  5. Broad Compatibility: Gdao theoretically supports all databases that implement the Go database driver interface.
  6. Advanced Features: Supports transactions, stored procedures, batch processing, and other database operations.
  7. Support SQL and program separation: Similar to mybatis, gdao supports xml file write sql mapping calls. This is one of the few orm features that supports the separation of SQL and programs, but it is very powerful.

GDAO’s Innovative ORM Solution

Gdao is a sibling framework to Jdao, sharing its design patterns.

  1. Standardized Mapped Entity Classes for Single Table CRUD Operations: Over 90% of single-table operations can be performed through entity classes. These CRUD operations are generally not involved in complex SQL optimization and can be generated by entity classes to reduce error rates and simplify maintenance.
    By utilizing mechanisms such as caching and read-write separation, the persistence layer becomes more efficient and convenient. The data operation format of standardized entity classes is not merely a concatenation of object functions but is more akin to SQL operations, making it easier to understand.
  2. Execution of Complex SQL: Complex SQL, especially multi-table joins, often require optimization based on the table structure and index properties. Using objects to concatenate complex SQL can increase the difficulty of understanding and may lead to developers being unaware of the final executed SQL, thereby increasing risk and maintenance difficulty.
    Therefore, Gdao recommends using Gdao’s CRUD interfaces for complex SQL problems. Gdao provides flexible data conversion and efficient object mapping implementations, avoiding excessive use of time-consuming operations such as reflection.
  3. SQL Mapping Files: For complex SQL operations, Gdao provides corresponding CRUD interfaces. It also supports mapping SQL through XML configuration for interface invocation, similar to the Java MyBatis ORM framework. However, unlike MyBatis which requires mapping all SQL operations, Gdao provides complete SQL mapping interfaces but recommends only mapping complex SQL or operations that standardized entity classes cannot complete.
    Gdao’s SQL configuration files reference the MyBatis configuration file format, implementing a new parser that allows for higher flexibility and tolerance of configuration parameter types (refer to the documentation).


Core Components

1. gdao

Main core entry point providing the following functionalities:

  • Setting data sources
  • SQL CRUD functions

2. gdaoCache

Cache entry point supporting the following functionalities:

  • Binding or unbinding packages, classes, and other properties to enable or disable query caching

3. gdaoSlave

Read-write separation operation entry point supporting the following functionalities:

  • Binding or unbinding packages, classes, and other properties to enable or disable read-write separation

4. gdaoMapper

Execute SQL directly by calling Gdao’s CRUD interfaces or use XML file mappings and call through gdaoMapper by Mapper Id


Quick Start

1. Installation

# import gdao
go get github.com/donnie4w/gdao

2. Configure Data Source

gdao.Init(mysqlDB, gdao.MYSQL)
// gdao.MYSQL is the database type

3. Generate Table Entity Classes

Use the Gdao code generation tool to generate standardized entity classes for database tables.

4. Entity Class Operations

// Set data source
gdao.Init(mysqlDB, gdao.MYSQL)

// Read
hs := dao.NewHstest()
hs.Where(hs.Id.EQ(10))
h, _ := hs.Select(hs.Id, hs.Value, hs.Rowname)
logger.Debug(h)
//[DEBUG][SELECT ONE][ select id, value, rowname from hstest where id=?][10]

// Update
hs := dao.NewHstest()
hs.SetRowname("hello10")
hs.Where(hs.Id.EQ(10))
hs.Update()
//[DEBUG][UPDATE][update hstest set rowname=? where id=?][hello10 10]

// Delete
hs := dao.NewHstest()
hs.Where(hs.Id.EQ(10))
hs.Delete()
//[DEBUG][DELETE][delete from hstest where id=?][10]

// Insert
hs := dao.NewHstest()
hs.SetValue("hello123")
hs.SetLevel(12345)
hs.SetBody([]byte("hello"))
hs.SetRowname("hello1234")
hs.SetUpdatetime(time.Now())
hs.SetFloa(123456)
hs.SetAge(123)
hs.Insert()
//[DEBUG][INSERT][insert into hstest(floa, age, value, level, body, rowname, updatetime) values(?,?,?,?,?,?,?)][123456 123 hello123 12345 [104 101 108 108 111] hello1234 2024-07-17 19:36:44]

5. gdao api

CRUD Operations
// Query, return single record
bean, _ := gdao.ExecuteQueryBean("select id, value, rowname from hstest where id=?", 10)
logger.Debug(bean)

// Insert
i := gdao.ExecuteUpdate("insert into hstest2(rowname, value) values(?,?)", "helloWorld", "123456789")

// Update
i := gdao.ExecuteUpdate("update hstest set value=? where id=1", "hello")

// Delete
i := gdao.ExecuteUpdate("delete from hstest where id = ?", 1)

6. gdaoCache

Configure Caching
// Bind Hstest to enable caching, cache expiration set to 300 seconds
gdaoCache.BindClass[dao.Hstest]()

// First query Hstest and set data cache based on conditions
hs := dao.NewHstest()
hs.Where((hs.Id.Between(0, 2)).Or(hs.Id.Between(10, 15)))
hs.Limit(3)
hs.Selects()

// For the same conditions, data is directly retrieved from cache
hs = dao.NewHstest()
hs.Where((hs.Id.Between(0, 2)).Or(hs.Id.Between(10, 15)))
hs.Limit(3)
hs.Selects()
Execution Result
[DEBUG][SELECT LIST][ select id, age, rowname, value, updatetime, body, floa, level from hstest where id between ? and ? or (id between ? and ?) LIMIT ? ][0 2 10 15 3]
[DEBUG][SET CACHE][ select id, age, rowname, value, updatetime, body, floa, level from hstest where id between ? and ? or (id between ? and ?) LIMIT ? ][0 2 10 15 3]
[DEBUG][SELECT LIST][ select id, age, rowname, value, updatetime, body, floa, level from hstest where id between ? and ? or (id between ? and ?) LIMIT ? ][0 2 10 15 3]
[DEBUG][GET CACHE][ select id, age, rowname, value, updatetime, body, floa, level from hstest where id between ? and ? or (id between ? and ?) LIMIT ? ][0 2 10 15 3]

7. gdaoSlave

Read-Write Separation
// Set slave data source: mysql
mysqlDB, _ := getDataSource("mysql.json")
gdaoSlave.BindClass[dao.Hstest](mysqlDB, gdao.MYSQL)
// Here the main database is sqlite and the slave database is mysql. Hstest reads data from mysql
hs := dao.NewHstest()
hs.Where(hs.Id.Between(0, 5))
hs.OrderBy(hs.Id.Desc())
hs.Limit(3)
hs.Selects()

8. gdaoMapper

Use XML to Map SQL
<!-- MyBatis style XML configuration file -->
<mapper namespace="user">
   <select id="selectHstest1" parameterType="int64" resultType="hstest1">
      SELECT * FROM hstest1 ORDER BY id DESC LIMIT #{limit}
   </select>
</mapper>
// Set data source
if db, err := getDataSource("sqlite.json"); err == nil {
   gdao.Init(db, gdao.SQLITE)  
   gdao.SetLogger(true)
}

// Read and parse XML configuration
hs1, _ := gdaoMapper.Select[dao.Hstest1]("user.selectHstest1", 1)
fmt.Println(hs1)

id, _ := gdaoMapper.Select[int64]("user.selectHstest1", 1)
fmt.Println(*id)
Execution Result
[DEBUG][Mapper Id] user.selectHstest1 
SELECTONE SQL[SELECT * FROM hstest1 ORDER BY id DESC LIMIT ?]ARGS[1]
Id:52, Rowname:rowname>>>123456789, Value:[104 101 108 108 111 32 103 100 97 111], Goto:[49 50 51 52 53]
[DEBUG][Mapper Id] user.selectHstest1 
SELECTONE SQL[SELECT * FROM hstest1 ORDER BY id DESC LIMIT ?]ARGS[1]
52
1 Like

gdaodemo
This is a test demo program for Gdao, including a packaged SQLite test database file hstest.db , with generated data. The demo program can be run directly. Except for testing read-write separation or multiple data source operations, other tests default to operating on the hstest.db database data and can be run directly to see the data operation results.