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安装
- 下载适用于您平台的Release
- 从
.tar.bz2
或.zip
文件中提取dbtpl
或dbtpl.exe
文件 - 将提取的可执行文件移动到您的
$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代码
- 首先创建一个输出目录:
mkdir -p models
- 然后运行dbtpl命令生成代码:
dbtpl schema postgres://user:pass@localhost/mydb -o models
- 生成的代码将包含类似以下内容的结构:
// 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
提供了一组通用的"基础"模板,但您也可以创建自己的自定义模板:
- 创建一个工作目录并转储基础模板:
mkdir -p my-tpl
dbtpl dump my-tpl
- 编辑基础模板文件:
vi my-tpl/*.go.tpl
- 使用自定义模板生成代码:
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 |
注意事项
-
dbtpl
生成的代码是生产质量的,但它不是"银弹",也不能完全消除手动编写SQL/Go代码的需要。 -
对于非平凡的Schema,自定义模板是最实用、最常见和最好的使用
dbtpl
的方式。 -
基础
dbtpl
模板不导入任何SQL驱动程序,用户需要自己导入实际的驱动程序。
更多关于golang从数据库Schema生成Go代码插件库xo的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于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目录下。
要使用自定义模板:
- 创建模板目录结构
- 修改需要的模板文件
- 使用
--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)
}
高级功能
- 自定义类型:使用
--custom-type
选项映射数据库类型到Go类型 - 复合主键:支持复合主键表的生成
- 外键关系:自动生成关联查询方法
- 存储过程:支持生成存储过程的调用代码
- 枚举类型:支持数据库枚举类型的生成
xo是一个强大的工具,可以显著减少数据库相关的样板代码编写工作,同时保持类型安全。