golang从数据库Schema生成Go代码插件库xo的使用

Golang从数据库Schema生成Go代码插件库xo的使用

dbtpl(原名为xo)是一个命令行工具,用于检查和生成基于数据库Schema或自定义数据库查询的模板代码。

功能概述

dbtpl不仅能为数据库生成标准化的"模型"代码,还能创建数据库的Schema创建脚本、生成JSON/YAML定义以及Schema的Graphviz图表。

支持的语言

目前dbtpl仅支持Go语言。支持其他语言是可能的,但目前没有计划。

工作原理

在Schema模式下,dbtpl连接到您的数据库并使用Go模板生成代码。它通过数据库元数据和SQL内省查询来发现Schema中包含的类型和关系,并对发现的关系应用一组标准的基础(或自定义)Go模板。

目前,dbtpl可以为PostgreSQL、MySQL、Oracle、Microsoft SQL Server和SQLite3数据库生成表、枚举、存储过程和自定义SQL查询的类型。

安装方式

通过Release安装

  1. 下载适用于您平台的Release
  2. .tar.bz2.zip文件中提取dbtpldbtpl.exe文件
  3. 将提取的可执行文件移动到您的$PATH(Linux/macOS)或%PATH%(Windows)中的某个位置

通过Homebrew安装(macOS和Linux)

brew install xo/xo/dbtpl

通过Go安装

go install github.com/xo/dbtpl@latest

快速入门

以下是在命令行中使用dbtpl的快速概述:

# 为生成的代码创建一个输出目录
mkdir -p models

# 从Postgres Schema生成代码(默认输出文件夹是models)
dbtpl schema postgres://user:pass@host/dbname

# 使用自定义模板目录从Microsoft SQL Schema生成代码
mkdir -p mssqlmodels
dbtpl schema mssql://user:pass@host/dbname -o mssqlmodels --src custom/templates

# 为Postgres从自定义SQL查询生成代码
dbtpl query postgres://user:pass@host/dbname -M -B -2 -T AuthorResult << ENDSQL
SELECT
  a.name::varchar AS name,
  b.type::integer AS my_type
FROM authors a
  INNER JOIN authortypes b ON a.id = b.author_id
WHERE
  a.id = %%authorID int%%
LIMIT %%limit int%%
ENDSQL

# 构建生成的代码 - 验证它是否能编译
go build ./models/
go build ./mssqlmodels/

完整示例

从PostgreSQL Schema生成Go代码

  1. 首先创建一个输出目录:
mkdir -p models
  1. 然后运行dbtpl命令生成代码:
dbtpl schema postgres://user:pass@localhost/mydb -o models
  1. 生成的代码将包含类似以下内容的结构:
// Package models contains generated code for the database schema.
package models

// User represents a row from the 'users' table.
type User struct {
    ID        int       `db:"id"`
    Name      string    `db:"name"`
    CreatedAt time.Time `db:"created_at"`
    // ...其他字段
}

// GetUserByID retrieves a user by ID.
func GetUserByID(ctx context.Context, db DB, id int) (*User, error) {
    // SQL查询和扫描逻辑
}

// Insert inserts a new User into the database.
func (u *User) Insert(ctx context.Context, db DB) error {
    // 插入逻辑
}

使用自定义查询生成代码

dbtpl query postgres://user:pass@localhost/mydb -T UserResult << ENDSQL
SELECT id, name, created_at 
FROM users
WHERE id = %%userID int%%
ENDSQL

这将生成一个UserResult类型和相应的查询函数。

自定义模板

dbtpl提供了一组通用的"基础"模板,但您也可以创建自己的自定义模板:

  1. 创建一个工作目录并转储基础模板:
mkdir -p my-tpl
dbtpl dump my-tpl
  1. 编辑基础模板文件:
vi my-tpl/*.go.tpl
  1. 使用自定义模板生成代码:
dbtpl schema --src my-tpl -o models postgres://user:pass@host/db

项目集成

理想情况下,您应该将项目的自定义模板与项目一起存储,并使用go generate作为自动化构建管道的一部分:

// 在gen.go文件中添加
package mypackage

//go:generate dbtpl postgres://user:pass@host/db -o models --src templates

然后运行:

go generate

数据库驱动支持

以下是dbtpl生成的代码预期使用的驱动程序:

数据库(driver)
PostgreSQL (postgres) github.com/lib/pq
SQLite3 (sqlite3) github.com/mattn/go-sqlite3
MySQL (mysql) github.com/go-sql-driver/mysql
Microsoft SQL Server (mssql) github.com/microsoft/go-mssqldb
Oracle (ora) github.com/sijms/go-ora/v2

注意事项

  1. dbtpl生成的代码是生产质量的,但它不是"银弹",也不能完全消除手动编写SQL/Go代码的需要。

  2. 对于非平凡的Schema,自定义模板是最实用、最常见和最好的使用dbtpl的方式。

  3. 基础dbtpl模板不导入任何SQL驱动程序,用户需要自己导入实际的驱动程序。


更多关于golang从数据库Schema生成Go代码插件库xo的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang从数据库Schema生成Go代码插件库xo的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


使用xo从数据库Schema生成Go代码

xo是一个强大的工具,可以从数据库schema自动生成类型安全的Go代码。它支持多种数据库(PostgreSQL, MySQL, SQLite, Oracle, Microsoft SQL Server)并能生成模型、查询、存储过程等代码。

安装xo

# 安装xo
go get -u github.com/xo/xo

# 安装数据库驱动(根据需要选择)
go get -u github.com/lib/pq      # PostgreSQL
go get -u github.com/go-sql-driver/mysql # MySQL
go get -u github.com/mattn/go-sqlite3    # SQLite

基本使用

1. 从数据库生成模型

# PostgreSQL示例
xo pgsql://user:pass@host/dbname -o models

# MySQL示例
xo mysql://user:pass@host/dbname -o models

# SQLite示例
xo file:path/to/db.sqlite3 -o models

2. 常用选项

# 指定包名
xo pgsql://user:pass@host/dbname -o models --package mymodels

# 忽略特定表
xo pgsql://user:pass@host/dbname -o models --ignore users,logs

# 只包含特定表
xo pgsql://user:pass@host/dbname -o models --include users,posts

# 添加自定义模板
xo pgsql://user:pass@host/dbname -o models --template-path /path/to/templates

生成代码示例

假设有一个简单的users表:

CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    email VARCHAR(100) UNIQUE NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

运行xo后会生成以下文件:

models/user.go

// Code generated by xo. DO NOT EDIT.

package models

import (
    "context"
    "time"
)

// User represents a row from 'public.users'.
type User struct {
    ID        int       `json:"id"`         // id
    Name      string    `json:"name"`       // name
    Email     string    `json:"email"`      // email
    CreatedAt time.Time `json:"created_at"` // created_at
    // xo fields
    _exists, _deleted bool
}

// Exists returns true when the User exists in the database.
func (u *User) Exists() bool {
    return u._exists
}

// Deleted returns true when the User has been marked for deletion from
// the database.
func (u *User) Deleted() bool {
    return u._deleted
}

// Insert inserts the User to the database.
func (u *User) Insert(ctx context.Context, db DB) error {
    // ...
}

// Update updates a User in the database.
func (u *User) Update(ctx context.Context, db DB) error {
    // ...
}

// Save saves the User to the database.
func (u *User) Save(ctx context.Context, db DB) error {
    if u.Exists() {
        return u.Update(ctx, db)
    }
    return u.Insert(ctx, db)
}

// Delete deletes the User from the database.
func (u *User) Delete(ctx context.Context, db DB) error {
    // ...
}

// UserByEmail retrieves a row from 'public.users' as a User.
func UserByEmail(ctx context.Context, db DB, email string) (*User, error) {
    // ...
}

models/xo_db.go

// Code generated by xo. DO NOT EDIT.

package models

import (
    "context"
    "database/sql"
    "fmt"
    "time"
)

// DB is the common interface for database operations.
type DB interface {
    ExecContext(context.Context, string, ...interface{}) (sql.Result, error)
    PrepareContext(context.Context, string) (*sql.Stmt, error)
    QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error)
    QueryRowContext(context.Context, string, ...interface{}) *sql.Row
}

自定义模板

xo允许使用自定义模板来生成代码。默认模板在xo/templates目录下。

要使用自定义模板:

  1. 创建模板目录结构
  2. 修改需要的模板文件
  3. 使用--template-path选项指定模板路径
xo pgsql://user:pass@host/dbname -o models --template-path /path/to/templates

在项目中使用生成的代码

package main

import (
    "context"
    "database/sql"
    "fmt"
    "log"
    
    "your_project/models"
    
    _ "github.com/lib/pq"
)

func main() {
    db, err := sql.Open("postgres", "postgres://user:pass@localhost/dbname?sslmode=disable")
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()
    
    // 创建新用户
    user := &models.User{
        Name:  "John Doe",
        Email: "john@example.com",
    }
    if err := user.Save(context.Background(), db); err != nil {
        log.Fatal(err)
    }
    
    // 查询用户
    fetchedUser, err := models.UserByEmail(context.Background(), db, "john@example.com")
    if err != nil {
        log.Fatal(err)
    }
    
    fmt.Printf("User: %+v\n", fetchedUser)
}

高级功能

  1. 自定义类型:使用--custom-type选项映射数据库类型到Go类型
  2. 复合主键:支持复合主键表的生成
  3. 外键关系:自动生成关联查询方法
  4. 存储过程:支持生成存储过程的调用代码
  5. 枚举类型:支持数据库枚举类型的生成

xo是一个强大的工具,可以显著减少数据库相关的样板代码编写工作,同时保持类型安全。

回到顶部