如何在TypeORM中为PostgreSQL定义自定义datemultirange类型?
解决TypeORM中PostgreSQL datemultirange类型支持问题
要在TypeORM中使用PostgreSQL的datemultirange类型,需要通过自定义列类型让TypeORM识别该类型,同时确保表创建和迁移生成时能正确处理。以下是具体实现步骤:
1. 定义自定义列类型类
创建一个继承自TypeORM AbstractDataType的类,明确指定PostgreSQL的datemultirange作为列类型,同时可选实现值的转换逻辑:
// src/types/DateMultiRange.ts import { AbstractDataType } from 'typeorm'; import { PostgresConnectionOptions } from 'typeorm/driver/postgres/PostgresConnectionOptions'; export class DateMultiRangeType extends AbstractDataType<PostgresConnectionOptions> { // 返回PostgreSQL的目标列类型 getColumnType(): string { return 'datemultirange'; } // 自定义类型名称,用于注册识别 getName(): string { return 'date-multi-range'; } // 可选:将JS中的日期范围数组转换为PostgreSQL的multirange格式 convertToDatabaseValue(value: [Date, Date][], driver: any): string | null { if (!value?.length) return null; const rangeSegments = value.map(([start, end]) => `("${start.toISOString().split('T')[0]}", "${end.toISOString().split('T')[0]}")` ).join(', '); return `{${rangeSegments}}`; } // 可选:将数据库返回的multirange字符串转换为JS数组 convertToJsValue(value: string, driver: any): [Date, Date][] | null { if (!value) return null; const trimmed = value.slice(1, -1); // 去除首尾的{} const rangeStrings = trimmed.split('),('); return rangeStrings.map(rangeStr => { const [startStr, endStr] = rangeStr.replace(/[()"]/g, '').split(','); return [new Date(startStr), new Date(endStr)]; }); } }
2. 在数据源配置中注册自定义类型
在TypeORM的DataSource配置里,将自定义类型添加到extra.types数组中,确保驱动能识别该类型:
// src/data-source.ts import { DataSource } from 'typeorm'; import { DateMultiRangeType } from './types/DateMultiRange'; import { Event } from './entities/Event'; export const AppDataSource = new DataSource({ type: 'postgres', host: 'localhost', port: 5432, username: 'postgres', password: 'your-password', database: 'your-db', entities: [Event], migrations: [__dirname + '/migrations/**/*.ts'], // 注册自定义列类型 extra: { types: [new DateMultiRangeType()], }, });
3. 在实体中使用自定义类型
在实体类的字段上,直接将@Column的type参数指定为自定义类型:
// src/entities/Event.ts import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm'; import { DateMultiRangeType } from '../types/DateMultiRange'; @Entity() export class Event { @PrimaryGeneratedColumn() id: number; // 使用自定义的datemultirange类型 @Column({ type: DateMultiRangeType, nullable: true }) dateRanges: [Date, Date][]; }
4. 验证表创建与迁移生成
- 表创建:运行
typeorm schema:sync命令,TypeORM会自动创建包含datemultirange类型列的表。 - 迁移生成:运行
typeorm migration:generate src/migrations/CreateEventTable,生成的迁移文件会正确使用datemultirange类型,示例如下:
import { MigrationInterface, QueryRunner } from "typeorm"; export class CreateEventTable1718000000000 implements MigrationInterface { public async up(queryRunner: QueryRunner): Promise<void> { await queryRunner.query(`CREATE TABLE "event" ("id" SERIAL NOT NULL, "dateRanges" datemultirange, CONSTRAINT "PK_30c2f3bbaf6d34a55f8ae6e4614" PRIMARY KEY ("id"))`); } public async down(queryRunner: QueryRunner): Promise<void> { await queryRunner.query(`DROP TABLE "event"`); } }
这样就完全实现了你需要的需求:表创建时识别datemultirange类型,生成迁移时自动进行类型检查。
内容的提问来源于stack exchange,提问作者Fedenko Maksym
相关产品推荐
相关产品推荐

