如何用TypeORM在PostgreSQL中存储含JSON对象数组的用户实体?
我明白你的问题了——你在使用TypeORM的嵌入实体(About)时,想要存储一个自定义对象数组(Softwares[]),但TypeORM没有原生支持这种类型,而且尝试用关联关系(ManyToOne)也不奏效,因为嵌入实体是和User存在同一张表中的,不是独立的实体。
下面是具体的解决方案:
核心思路
因为About是嵌入实体(通过@Column(() => About)实现),它的所有字段都会被映射到User表的列中,而不是生成单独的表。所以我们不能用关联关系(比如ManyToOne)来处理softwares数组,而是需要把它作为一个JSON类型的列存储,同时处理好TypeScript类和数据库JSON格式之间的转换。
具体实现步骤
选择合适的JSON列类型:根据你的数据库选择对应的类型,比如PostgreSQL推荐用
jsonb(支持索引和更高效的查询),MySQL/MariaDB用json,SQLite可以用text(但要手动处理JSON转换)。为softwares字段添加TypeORM Column配置:在About类的softwares字段上添加
@Column装饰器,指定类型为JSON,并配置转换器(transformer)来实现Softwares[]和数据库JSON的互相转换。
修改后的About类代码如下:
@ObjectType() export class About { @Field( { nullable: true } ) @Column("text", { nullable: true }) about_header_message: string; // 修改这里的配置 @Field(() => [Softwares], { nullable: true }) @Column({ type: 'jsonb', // 如果你用PostgreSQL,推荐jsonb;用MySQL的话改成'json' nullable: true, transformer: { // 把Softwares数组转换成数据库能存储的JSON格式 to: (value: Softwares[]) => value, // 把数据库返回的JSON转换成Softwares数组(如果需要类实例,用Object.assign) from: (value: any) => { if (!Array.isArray(value)) return []; return value.map((item: any) => Object.assign(new Softwares(), item)); }, }, }) softwares: Softwares[]; @Field(() => [[String]], { nullable: true }) @Column("text", { nullable: true, array: true }) info: string[][]; }
为什么关联关系行不通?
你之前尝试的ManyToOne是用于独立实体之间的关联,比如一个User关联多个独立的Software实体(对应单独的software表)。但你的场景中,Softwares是属于About嵌入实体的一部分,它的数据和User存在同一张表中,不是单独的表,所以关联关系不适用。
验证效果
这样配置后:
- TypeORM会把softwares数组作为JSON类型存储到User表的
aboutSoftwares列(嵌入实体的字段会自动加上前缀) - TypeGraphQL的字段配置保持不变,所以GET请求返回的结构依然和你预期的一致
- 当你从数据库查询User时,transformer会自动把JSON数据转换成Softwares类的实例数组
额外注意事项
- 如果你的数据库不支持原生JSON类型(比如旧版本的SQLite),可以把类型设为
text,然后在transformer的to方法里用JSON.stringify(value),from方法里用JSON.parse(value)来处理 - 如果你不需要Softwares的类实例,只是普通的JS对象,transformer的
from方法可以简化为(value: any) => value || [] - 如果你开启了TypeORM的
synchronize: true,它会自动帮你在User表中创建对应的JSON列;如果是已有数据库,需要手动添加该列
内容的提问来源于stack exchange,提问作者nullmage




