sujanto-gaws/genbun

GitHub: sujanto-gaws/genbun

一个基于 Go 的 CLI 工具,从 PostgreSQL 自动生成 Bun ORM 模型,解决手动编写 ORM 结构的繁琐问题。

Stars: 0 | Forks: 0

# genbun - PostgreSQL 到 Bun ORM 模型生成器 一个强大的 CLI 工具,可以从 PostgreSQL 数据库架构自动生成带有 Bun ORM 标签的 Go 模型,类似于 EF Core 工具。 ## 功能特性 - **自动架构检测**:从 PostgreSQL 读取表、列、主键和约束 - **关系检测**:自动检测并生成 BelongsTo、HasMany 和 ManyToMany 关系 - **外部模板系统**:使用外部模板文件自定义生成的模型 - **Bun ORM 标签**:生成适当的 `bun` 结构体标签,用于无缝 ORM 映射,包括关系 - **类型映射**:智能的 PostgreSQL 到 Go 类型转换 - **可空支持**:使用指针类型正确处理可空列 - **可定制**:通过 YAML 文件、环境变量或 CLI 标志进行灵活配置 - **简洁输出**:生成格式良好、符合 Go 语言习惯的代码 - **表过滤**:包含或排除特定表 - **多架构支持**:适用于任何 PostgreSQL 架构 ## 安装 ### 从源码安装 ``` go install github.com/sujanto-gaws/genbun@latest ``` ### 从仓库构建 ``` git clone cd genbun go build -o genbun.exe . ``` ## 快速开始 ### 1. 初始化配置 ``` genbun init ``` 这会创建一个带有默认设置的 `genbun.yaml` 配置文件。 ### 2. 配置数据库连接 编辑 `genbun.yaml`: ``` database: host: localhost port: 5432 user: your_username password: your_password dbname: your_database sslmode: disable output: path: internal/model package: model overwrite: true generate: schema: public tables: [] # Leave empty to generate all tables exclude_tables: [] # Tables to exclude ``` ### 3. 生成模型 ``` genbun generate ``` ## 用法 ### CLI 命令 #### 初始化配置 ``` genbun init ``` 创建一个默认的配置文件。 #### 生成模型 ``` genbun generate [flags] ``` ### 命令行标志 | 标志 | 简写 | 描述 | 默认值 | |------|-------|-------------|---------| | `--config` | | 配置文件路径 | `./genbun.yaml` | | `--output` | | 输出目录 | (来自配置) | | `--package` | | 包名 | (来自配置) | | `--tables` | `-t` | 要生成的表(逗号分隔) | 所有表 | | `--exclude` | `-e` | 要排除的表(逗号分隔) | 无 | | `--schema` | `-s` | 数据库架构 | `public` | | `--verbose` | `-v` | 启用详细输出 | `false` | ### 示例 **生成所有表:** ``` genbun generate ``` **生成特定表:** ``` genbun generate -t users,posts,comments ``` **排除某些表:** ``` genbun generate -e migrations,schema_versions ``` **自定义输出:** ``` genbun generate --output pkg/models --package models ``` **详细模式:** ``` genbun generate -v ``` **使用自定义配置文件:** ``` genbun generate --config configs/genbun-prod.yaml ``` ## 配置 ### 环境变量 genbun 支持带有 `GENBUN_` 前缀的环境变量: ``` export GENBUN_DATABASE_HOST=localhost export GENBUN_DATABASE_USER=myuser export GENBUN_DATABASE_PASSWORD=mypass export GENBUN_DATABASE_DBNAME=mydb export GENBUN_OUTPUT_PATH=internal/model ``` ### 配置选项 #### 数据库配置 | 选项 | 描述 | 默认值 | |--------|-------------|---------| | `database.host` | PostgreSQL 主机 | `localhost` | | `database.port` | PostgreSQL 端口 | `5432` | | `database.user` | 数据库用户 | `` | | `database.password` | 数据库密码 | `` | | `database.dbname` | 数据库名 | `` | | `database.sslmode` | SSL 模式 | `disable` | #### 输出配置 | 选项 | 描述 | 默认值 | |--------|-------------|---------| | `output.path` | 输出目录 | `internal/model` | | `output.package` | 包名 | `model` | | `output.overwrite` | 覆盖现有文件 | `true` | | `output.prefix` | 从表名中移除的前缀 | `` | | `output.suffix` | 添加到模型名的后缀 | `` | #### 生成配置 | 选项 | 描述 | 默认值 | |--------|-------------|---------| | `generate.tables` | 要包含的表 | 所有表 | | `generate.exclude_tables` | 要排除的表 | `[]` | | `generate.schema` | 数据库架构 | `public` | ## 类型映射 genbun 自动将 PostgreSQL 类型映射到 Go 类型: | PostgreSQL 类型 | Go 类型 | |----------------|---------| | `boolean` | `bool` | | `smallint` / `int2` | `int16` | | `integer` / `int4` / `serial` | `int32` | | `bigint` / `int8` / `bigserial` | `int64` | | `real` / `float4` | `float32` | | `double precision` / `float8` | `float64` | | `numeric` / `decimal` | `int64` 或 `float64` | | `varchar` / `text` / `char` | `string` | | `uuid` | `string` | | `date` / `timestamp` / `timestamptz` | `time.Time` | | `time` | `time.Time` | | `json` / `jsonb` | `[]byte` | | `bytea` | `[]byte` | | `inet` / `cidr` | `string` | 可空列会生成为指针类型(例如 `*string`、`*int64`)。 ## 关系检测 genbun 会自动从外键约束中检测关系: ### 关系类型 | 类型 | 描述 | Bun 标签 | |------|-------------|---------| | **BelongsTo** | 本表中的外键引用另一张表 | `bun:"rel:belongs-to,join:fk_column=target.id"` | | **HasMany** | 其他表有外键引用本表 | `bun:"rel:has-many,join:id=source.fk_column"` | | **ManyToMany** | 两张表通过一个连接表连接 | `bun:"rel:many-to-many,join:..."` | ### 工作原理 1. **BelongsTo**:当一张表有外键时,genbun 会生成一个引用目标模型的字段 2. **HasMany**:自动添加到被引用表(BelongsTo 的反向关系) 3. **ManyToMany**:当一个表恰好有 2 个外键且具有复合主键时检测到 ### 使用关系 ``` // Query with relations user := &model.User{ID: 1} err := db.NewSelect().Model(user).Relation("Posts").Scan(ctx) // Access related data fmt.Printf("User: %s\n", user.Username) fmt.Printf("Posts: %d\n", len(user.Posts)) // Nested relations err := db.NewSelect().Model(user). Relation("Posts"). Relation("Posts.Tags"). Relation("Posts.User"). Scan(ctx) ``` ## 生成的代码示例 ### 带有关系的数据库架构 ``` CREATE TABLE users ( id SERIAL PRIMARY KEY, username VARCHAR(100) NOT NULL, email VARCHAR(255) NOT NULL, created_at TIMESTAMP DEFAULT NOW() ); CREATE TABLE posts ( id SERIAL PRIMARY KEY, user_id INTEGER NOT NULL REFERENCES users(id), title VARCHAR(200) NOT NULL, content TEXT, created_at TIMESTAMP DEFAULT NOW() ); CREATE TABLE tags ( id SERIAL PRIMARY KEY, name VARCHAR(50) UNIQUE NOT NULL ); CREATE TABLE post_tags ( post_id INTEGER REFERENCES posts(id), tag_id INTEGER REFERENCES tags(id), PRIMARY KEY (post_id, tag_id) ); ``` ### 带有关系的生成 Go 模型 #### User 模型(拥有多个 Post) ``` // Code generated by genbun. DO NOT EDIT. // Generated at 2026-04-13 10:30:00 package model import ( "time" ) // User represents the users table. type User struct { ID int32 `bun:"id,pk,autoincrement"` Username string `bun:"username"` Email string `bun:"email"` CreatedAt time.Time `bun:"created_at"` // has_many relationship to posts Posts []Post `bun:"rel:has-many,join:id=posts.user_id"` } // TableName overrides the default table name. func (m *User) TableName() string { return "users" } ``` #### Post 模型(属于 User,ManyToMany 标签) ``` // Code generated by genbun. DO NOT EDIT. // Generated at 2026-04-13 10:30:00 package model import ( "time" ) // Post represents the posts table. type Post struct { ID int32 `bun:"id,pk,autoincrement"` UserID int32 `bun:"user_id"` Title string `bun:"title"` Content *string `bun:"content"` CreatedAt time.Time `bun:"created_at"` // belongs_to relationship to users User User `bun:"rel:belongs-to,join:user_id=users.id"` // many_to_many relationship to tags Tags []Tag `bun:"rel:many-to-many,join:post_id=post_tags.tag_id,join:post_tags.post_id=tags"` } // TableName overrides the default table name. func (m *Post) TableName() string { return "posts" } ``` #### Tag 模型(ManyToMany 到 Posts) ``` // Code generated by genbun. DO NOT EDIT. // Generated at 2026-04-13 10:30:00 package model // Tag represents the tags table. type Tag struct { ID int32 `bun:"id,pk,autoincrement"` Name string `bun:"name"` // many_to_many relationship to posts Posts []Post `bun:"rel:many-to-many,join:tag_id=post_tags.post_id,join:post_tags.tag_id=posts"` } // TableName overrides the default table name. func (m *Tag) TableName() string { return "tags" } ``` ## 项目结构 ``` genbun/ ├── cmd/ # CLI commands │ ├── root.go # Root command │ ├── init.go # Init command │ └── generate.go # Generate command ├── pkg/ │ ├── config/ # Configuration management │ │ └── config.go │ ├── database/ # Database schema reader │ │ └── schema.go │ └── generator/ # Model generator │ └── generator.go ├── main.go # Entry point ├── go.mod └── genbun.yaml # Configuration file ``` ## 高级用法 ### 处理大型数据库 对于包含许多表的数据库,使用 `--tables` 标志来生成特定表: ``` genbun generate -t users,user_roles,roles ``` ### 多架构 如果使用多个架构,请指定架构: ``` genbun generate --schema analytics ``` ### 模型命名 使用配置中的前缀/后缀选项控制模型命名: ``` output: prefix: "tbl_" # Remove tbl_ prefix from table names suffix: "Model" # Add Model suffix to struct names ``` ## 故障排除 ### 连接问题 - 验证 `genbun.yaml` 中的数据库凭据 - 检查数据库是否可访问 - 确保用户有足够的权限读取架构信息 ### 未生成表 - 验证架构名称是否正确 - 检查指定架构中是否存在表 - 检查 `exclude_tables` 配置 ### 类型映射问题 - 未知类型默认为 `string` - 自定义类型可能需要手动调整 - 查看详细输出中的警告 ## 与 EF 工具的对比 genbun 提供与 Entity Framework Core 工具类似的功能: | EF Core 工具 | genbun 等效 | |--------------|-------------------| | `dotnet ef dbcontext scaffold` | `genbun generate` | | `--output-dir` | `--output` | | `--schema` | `--schema` | | `--table` | `--tables` | | `appsettings.json` | `genbun.yaml` | ##许可证 本项目开源,采用 MIT 许可证。 ## 支持 如有问题、疑问或建议,请在仓库中打开 issue。
标签:Bun ORM, EVTX分析, Go, Hakrawler, ORM生成, PostgreSQL, Ruby工具, Schema解析, YAML, 一对多, 二进制发布, 代码格式化, 代码生成, 关系检测, 外键关联, 多对多, 威胁情报, 安全库, 开发者工具, 开源工具, 恶意代码分析, 数据库逆向工程, 文档结构分析, 日志审计, 模型生成, 模板引擎, 测试用例, 渗透测试工具, 空值处理, 类型映射, 结构体标签, 配置文件