名称: bknd-create-entity 描述: 在Bknd中创建新实体/表时使用。涵盖使用em()和entity()定义实体、主键配置、字段基础、通过管理面板进行UI创建以及具有类型安全的代码优先方法。
创建实体
在Bknd中创建一个新的实体(数据库表)。实体是数据模型的基础。
先决条件
- Bknd项目已初始化(
npx bknd create或现有项目) - 对于代码模式:已安装
bknd包的TypeScript项目
何时使用UI模式 vs 代码模式
使用UI模式当
- 快速探索/原型设计
- 非开发者或视觉学习者
- 进行一次性更改
- 在提交代码前测试模式想法
使用代码模式当
- 需要版本控制
- 跨环境的可重复设置
- 团队协作
- CI/CD管道
- 需要类型安全
UI方法
步骤1:访问管理面板
- 启动Bknd服务器:
npx bknd run - 在浏览器中打开
http://localhost:1337(默认端口) - 导航到侧边栏中的 数据 部分
步骤2:创建实体
- 点击 + 添加实体 按钮
- 输入实体名称(使用复数、小写:
posts、users、comments) - 配置主键格式:
- 整数(默认):自动递增ID
- UUID:通用唯一标识符
- 点击 创建
步骤3:添加字段
实体创建后,进入字段编辑器:
- 点击 + 添加字段
- 选择字段类型(文本、数字、布尔、日期、枚举、json)
- 配置字段选项:
- 名称:snake_case(例如:
first_name、created_at) - 必填:切换如果字段不能为null
- 默认值:可选默认值
- 名称:snake_case(例如:
- 点击 保存字段
- 重复添加其他字段
步骤4:同步模式
点击 同步数据库 将更改应用到实际数据库。
代码方法
步骤1:导入依赖项
import { em, entity, text, number, boolean, date, enumm, json } from "bknd";
步骤2:定义实体
在 em() 内创建实体:
const schema = em({
posts: entity("posts", {
title: text().required(),
content: text(),
published: boolean({ default_value: false }),
view_count: number({ default_value: 0 }),
}),
});
步骤3:配置主键(可选)
默认是自动递增整数。对于UUID:
const schema = em({
posts: entity("posts", {
title: text().required(),
}, {
primary_format: "uuid",
}),
});
步骤4:导出类型
启用类型安全查询:
const schema = em({
posts: entity("posts", {
title: text().required(),
content: text(),
}),
});
// 提取并声明类型
type Database = (typeof schema)["DB"];
declare module "bknd" {
interface DB extends Database {}
}
步骤5:在应用配置中使用
import { App } from "bknd";
const app = new App({
data: schema,
// ... 其他配置
});
完整示例
import { App, em, entity, text, number, boolean, date } from "bknd";
const schema = em({
users: entity("users", {
email: text().required().unique(),
name: text(),
active: boolean({ default_value: true }),
}),
posts: entity("posts", {
title: text().required(),
content: text(),
published: boolean({ default_value: false }),
published_at: date(),
}),
});
type Database = (typeof schema)["DB"];
declare module "bknd" {
interface DB extends Database {}
}
const app = new App({
data: schema,
});
export default app;
实体命名约定
| 约定 | 示例 | 备注 |
|---|---|---|
| 复数 | users, posts |
不是 user, post |
| 小写 | blog_posts |
不是 BlogPosts |
| snake_case | user_profiles |
不是 userProfiles |
自动生成的字段
每个实体自动包含:
| 字段 | 类型 | 描述 |
|---|---|---|
id |
整数/uuid | 主键(格式取决于配置) |
注意: 对于 created_at/updated_at,使用时间戳插件或手动添加:
entity("posts", {
title: text().required(),
created_at: date({ default_value: "now" }),
updated_at: date(),
})
常见陷阱
实体已存在
错误: 实体 "posts" 已定义
修复: 每个实体名称在 em() 内必须唯一。检查重复项。
无效的实体名称
错误: 无效的实体名称
修复: 仅使用小写字母、数字和下划线。必须以字母开头。
// ✅ 有效
entity("posts", { ... })
entity("user_profiles", { ... })
entity("blog_posts_2024", { ... })
// ❌ 无效
entity("Posts", { ... }) // 无大写
entity("2024_posts", { ... }) // 不能以数字开头
entity("post-items", { ... }) // 无连字符
模式未同步
问题: 在代码中创建了实体,但数据库中不存在表。
修复: 确保在应用配置中使用模式:
const app = new App({
data: schema, // 必须在此处传递模式
});
然后重启服务器 - Bknd在启动时自动同步。
缺少类型安全
问题: api.data.readMany("posts", ...) 没有类型提示。
修复: 添加类型声明:
type Database = (typeof schema)["DB"];
declare module "bknd" {
interface DB extends Database {}
}
验证
UI模式
- 检查实体是否出现在数据部分
- 点击实体查看字段
- 尝试创建测试记录
代码模式
// 应用启动后,验证实体存在
const api = app.getApi();
const result = await api.data.readMany("posts");
console.log(result); // 应该返回 { data: [] } 对于空实体
CLI检查
npx bknd debug routes
# 应该显示 /api/data/posts 端点
做与不做
做:
- 使用复数、小写的实体名称
- 从基本字段开始;稍后添加更多
- 为类型安全添加类型声明
- 对于分布式系统使用
primary_format: "uuid"
不做:
- 使用单数名称(如
user而不是users) - 对实体名称使用PascalCase或camelCase
- 创建没有至少一个字段的实体
- UI更改后忘记同步数据库
相关技能
- bknd-add-field - 向现有实体添加字段
- bknd-define-relationship - 使用关系连接实体
- bknd-modify-schema - 重命名或更改实体配置
- bknd-delete-entity - 安全移除实体