SkillAgentSearch skills...

Zorm

Go轻量ORM,支持达梦(dm),金仓(kingbase),神通(shentong),南大通用(gbase),TDengine,mysql,postgresql,oracle,mssql,sqlite,db2,clickhouse...

Install / Use

/learn @springrain/Zorm
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Introduction

zorm logo
This is a lightweight ORM,zero dependency, that supports DM,Kingbase,shentong,TDengine,mysql,postgresql,oracle,mssql,sqlite,db2,clickhouse...

Official website:https://zorm.cn
source code address:https://gitee.com/chunanyong/zorm || https://gitcode.com/springrain/zorm
test case: https://gitee.com/wuxiangege/zorm-examples/
Video tutorial: https://www.bilibili.com/video/BV1L24y1976U/

go get gitee.com/chunanyong/zorm 
  • Based on native SQL statements, the learning cost is lower
  • Code generator
  • The code is concise, the main body is 3000 lines, zero dependency 5000 lines, detailed comments, easy to customize and modify
  • <font color=red>Support for transaction propagation, which was the main reason for the birth of ZORM</font>
  • Support dm (dameng), kingbase (jincang), shentong (Shentong), gbase (Nantong), TDengine, mysql, postgresql, oracle, mssql, sqlite, db2, clickhouse...
  • Supports multi-database and read/write splitting
  • Joint primary keys are not supported, workarounds are assumed to be no primary keys, and business control is implemented (difficult trade-offs)
  • Support seata, HPTX, dbpack distributed transactions, support global transaction hosting, do not modify business code, zero intrusion distributed transactions
  • Support clickhouse, update, delete statements using SQL92 standard syntax

Transaction propagation

Transaction propagation is the core function of ZORM and the main reason why all methods of ZORM have ctx parameters.
ZORM transaction operations need zorm.Transaction(ctx, func(ctx context.Context) (interface{}, error) {}) to be explicitly enabled, check transactions before executing closure functions, join transactions if there are transactions in ctx, and create new transactions if there are no transactions in ctx, so you only need to pass the same ctx object to achieve transaction propagation. In special scenarios, if you do not want transaction synchronization, you can declare a new ctx object to do transaction isolation.

Description of the source repository

The main libraries of the open source projects I led are all in GitHub, and there are project descriptions on GitHub to guide the jump to GitHub, which also causes the slow growth of the project, after all, there are more GitHub users.
Open source has no borders, but developers have their own homeland.
Strictly speaking, GitHub is governed by US law https://www.infoq.cn/article/SA72SsSeZBpUSH_ZH8XB do my best to support the domestic open source community, don't like it, don't spray, thank you!

Support domestic database

ZORM spares no effort in adapting to domestic databases, and if you encounter domestic databases that are not adapted or have problems, please feedback to the community and work together to build a domestic software ecosystem

Da Meng (DM)

  • Configure zorm.DataSourceConfig DriverName:dm ,Dialect:dm
  • Damon Database Driver: gitee.com/chunanyong/dm
  • The TEXT type of Damon will be mapped to dm.DmClob, string cannot be received, and zorm needs to be implemented ICustomDriverValueConver interface, custom extension processing
import (
	// 00. Introduce the database driver
	"gitee.com/chunanyong/dm"
	"io"
)

// CustomDMText implements ICustomDriverValueConver interface to extend custom types. For example, the TEXT type is mapped to dm.DmClob and cannot be directly received using string
type CustomDMText struct{}

// GetDriverValue Returns an instance of driver.Value, the struct attribute type, based on the database column type
// The structFieldType is passed nil because the map received or field does not exist
func (dmtext CustomDMText) GetDriverValue(ctx context.Context, columnType *sql.ColumnType, structFieldType *reflect.Type) (driver.Value, error) {
	// If you want to use the structFieldType, you need to determine if it is nil
	// if structFieldType != nil {
	// }

	return &dm.DmClob{}, nil
}

// ConverDriverValue database column type, temporary received Value of driver. value returned by GetDriverValue,struct attribute type
// The structFieldType is passed nil because the map received or field does not exist
// Returns a pointer, pointer, pointer that matches the received type value!!!!
func (dmtext CustomDMText) ConverDriverValue(ctx context.Context, columnType *sql.ColumnType, tempDriverValue driver.Value, structFieldType *reflect.Type) (interface{}, error) {
	// If you want to use the structFieldType, you need to determine if it is nil
	// if structFieldType != nil {
	// }

	// Type conversion
	dmClob, isok := tempDriverValue.(*dm.DmClob)
	if !isok {
		return tempDriverValue, errors.New("->ConverDriverValue--> Failed to convert to *dm.DmClob")
	}
	if dmClob == nil || !dmClob.Valid {
		return new(string), nil
	}
	// Get the length
	dmlen, errLength := dmClob.GetLength()
	if errLength != nil {
		return dmClob, errLength
	}

	// int64 is converted to an int
	dmlenInt, errConvert := zorm.typeConvertInt64toInt(dmlen)
	if errConvert != nil {
		return dmClob, errConvert
	}

	// Read the string
	str, errReadString := dmClob.ReadString(1, dmlenInt)

	// Handle EOF errors caused by empty strings or NULL value
	if errReadString == io.EOF {
		return new(string), nil
	}

	return &str, errReadString
}
// RegisterCustomDriverValueConver registered custom field processing logic, used to drive not directly convert scenarios, such as the TEXT of the dream cannot directly into a string
// It's usually registered in the init method
func init() {
	// dialectColumnType is a Dialect.FieldType, such as dm.TEXT
	zorm.RegisterCustomDriverValueConver("dm.TEXT", CustomDMText{})
}

Kingbase

  • Configure zorm.DataSourceConfig DriverName:kingbase ,Dialect:kingbase
  • Golden warehouse official drive: https://www.kingbase.com.cn/qd/index.htmhttps://bbs.kingbase.com.cn/thread-14457-1-1.html?_dsign=87f12756
  • The Kingbase 8 core is based on PostgreSQL 9.6 and can be tested using https://github.com/lib/pq, and the official driver is recommended for production environments
  • Note that ora_input_emptystr_isnull = false or ora_input_emptystr_isnull = on in the data/kingbase.conf of the database (according to the version), because golang does not have a null value, the general database is not null, golang's string defaults to '', if this is set to true, The database will set the value to null, which conflicts with the field property not null, so an error is reported.After the configuration file is modified, restart the database.

Shentong (shentong)

It is recommended to use official driver, configure zorm.DataSourceConfig DriverName:aci ,Dialect:shentong

Nantong (gbase)

~~The official Go driver has not been found yet. Please configure it zorm.DataSourceConfig DriverName:gbase ,Dialect:gbase~~
Use odbc driver for the time being, DriverName:odbc ,Dialect:gbase

TDengine

  • Since the TDengine driver does not support transactions, you need to set this setting DisableTransaction=true
  • Configure zorm.DataSourceConfig DriverName:taosSql/taosRestful, Dialect:tdengine
  • zorm.DataSourceConfigInsertSQLNoColumnWhether the insert statement has no column names. True means no column names, the inserted values follow the order of the database columns, reducing the length of the statement
  • Test case: https://zorm.cn/docs/zorm_tdengine_3_test
  • TDengine is included: https://github.com/taosdata/awesome-tdengine/#orm

Database scripts and entity classes

Generate entity classes or write them manually, we recommend using a code generator https://gitee.com/zhou-a-xing/zorm-generate-struct


package testzorm

import (
	"time"

	"gitee.com/chunanyong/zorm"
)

// Build a list sentence

/*

DROP TABLE IF EXISTS `t_demo`;
CREATE TABLE `t_demo` (
`id` varchar(50) NOT NULL COMMENT 'primary key ',
`user_name` varchar(30) NOT NULL COMMENT 'name ',
`password` varchar(50) NOT NULL COMMENT 'password ',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
`active` int COMMENT 'Whether it is valid (0 no,1 yes)',
 PRIMARY KEY (`id`)
ENGINE = InnoDB CHARACTER SET = utf8mb4 COMMENT = 'example';

*/

// demoStructTableName Table name constant for direct call
const demoStructTableName = "t_demo"

// demoStruct example
type demoStruct struct {
	// Introduce the default struct to isolate method changes to the IEntityStruct
	zorm.EntityStruct

	// Id Primary key
	Id string `column:"id"`

	// UserName Specifies the name
	UserName string `column:"user_name"`

	// Password Password
	Password string `column:"password"`

	// CreateTime <no value>
	CreateTime time.Time `column:"create_time"`

	// Active Whether it is valid (0 No,1 yes)
	// Active int `column:"active"`

	// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - end of the database field, custom fields to write in the following -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- // 
	// If the queried field is not found in the column tag, it is mapped to the struct property by name (case insensitive, support _ _ to _ hump)

	// Simulates the custom field Active
	Active int
}

// GetTableName Gets the table name
// IEntityStruct interface method, entity class needs to implement!!
func (entity *demoStruct) GetTableName() string {
	return demoStructTableName
}

// GetPKColumnName Gets the name of the primary key field of the database table. Because to be compatible with Map, can only be the database field name
// Joint primary key is not supported. It can be considered that there is no primary key and service control can be realized (hard choice).
// If you do not have a primary key, you need to implement this method as well
// IEntityStruct interface method, entity class needs to implement!!
func (entity *demoStruct) GetPKColumnName() string {
	// If there is no primary key
	// return ""
	return "id"
}

// GetDefaultValue To get the default value of the Map, Only used for Insert
View on GitHub
GitHub Stars79
CategoryData
Updated1h ago
Forks6

Languages

Go

Security Score

100/100

Audited on Mar 29, 2026

No findings