Entidades
Esta página fue traducida por PageTurner AI (beta). No está respaldada oficialmente por el proyecto. ¿Encontraste un error? Reportar problema →
¿Qué es una Entidad?
Una entidad es una clase que se mapea a una tabla de base de datos (o colección al usar MongoDB).
Puedes crear una entidad definiendo una nueva clase y marcándola con @Entity():
import { Entity, PrimaryGeneratedColumn, Column } from "typeorm"
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number
@Column()
firstName: string
@Column()
lastName: string
@Column()
isActive: boolean
}
Esto creará la siguiente tabla en la base de datos:
+-------------+--------------+----------------------------+
| user |
+-------------+--------------+----------------------------+
| id | int | PRIMARY KEY AUTO_INCREMENT |
| firstName | varchar(255) | |
| lastName | varchar(255) | |
| isActive | boolean | |
+-------------+--------------+----------------------------+
Las entidades básicas constan de columnas y relaciones. Cada entidad DEBE tener una columna primaria (o columna ObjectId si usas MongoDB).
Cada entidad debe registrarse en las opciones de tu fuente de datos:
import { DataSource } from "typeorm"
import { User } from "./entities/User"
const myDataSource = new DataSource({
type: "mysql",
host: "localhost",
port: 3306,
username: "test",
password: "test",
database: "test",
entities: [User],
})
O puedes especificar todo el directorio con todas las entidades dentro, y todas se cargarán:
import { DataSource } from "typeorm"
const dataSource = new DataSource({
type: "mysql",
host: "localhost",
port: 3306,
username: "test",
password: "test",
database: "test",
entities: [__dirname + "/entities/**/*{.js,.ts}"],
})
Si deseas usar un nombre alternativo de tabla para la entidad User, puedes especificarlo en @Entity: @Entity("my_users").
Si quieres establecer un prefijo base para todas las tablas de tu aplicación, puedes especificar entityPrefix en las opciones de la fuente de datos.
Al usar un constructor de entidad, sus argumentos deben ser opcionales. Como el ORM crea instancias de clases de entidad al cargar desde la base de datos, no conoce los argumentos de tu constructor.
Aprende más sobre los parámetros de @Entity en la Referencia de decoradores.
Columnas de entidad
Como las tablas de bases de datos constan de columnas, tus entidades también deben tener columnas.
Cada propiedad de clase de entidad que marques con @Column se mapear á a una columna de tabla de base de datos.
Columnas primarias
Cada entidad debe tener al menos una columna primaria. Existen varios tipos de columnas primarias:
@PrimaryColumn()crea una columna primaria que acepta cualquier valor de cualquier tipo. Puedes especificar el tipo de columna. Si no especificas un tipo, se inferirá del tipo de propiedad. El siguiente ejemplo creará un id de tipointque debes asignar manualmente antes de guardar.
import { Entity, PrimaryColumn } from "typeorm"
@Entity()
export class User {
@PrimaryColumn()
id: number
}
@PrimaryGeneratedColumn()crea una columna primaria cuyo valor se generará automáticamente con un autoincremento. Creará una columnaintconauto-increment/serial/sequence/identity(dependiendo de la base de datos y configuración). No necesitas asignar su valor manualmente antes de guardar; el valor se generará automáticamente.
import { Entity, PrimaryGeneratedColumn } from "typeorm"
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number
}
@PrimaryGeneratedColumn("uuid")crea una columna primaria cuyo valor se generará automáticamente conuuid. Uuid es un identificador único de cadena. No necesitas asignar su valor manualmente antes de guardar; el valor se generará automáticamente.
import { Entity, PrimaryGeneratedColumn } from "typeorm"
@Entity()
export class User {
@PrimaryGeneratedColumn("uuid")
id: string
}
También puedes tener columnas primarias compuestas:
import { Entity, PrimaryColumn } from "typeorm"
@Entity()
export class User {
@PrimaryColumn()
firstName: string
@PrimaryColumn()
lastName: string
}
Cuando guardas entidades usando save, siempre intenta encontrar una entidad en la base de datos con el id (o ids) dado.
Si se encuentra el id/ids, actualizará esa fila en la base de datos.
Si no hay fila con ese id/ids, se insertará una nueva fila.
Para encontrar una entidad por id puedes usar manager.findOneBy o repository.findOneBy. Ejemplo:
// find one by id with single primary key
const person = await dataSource.manager.findOneBy(Person, { id: 1 })
const person = await dataSource.getRepository(Person).findOneBy({ id: 1 })
// find one by id with composite primary keys
const user = await dataSource.manager.findOneBy(User, {
firstName: "Timber",
lastName: "Saw",
})
const user = await dataSource.getRepository(User).findOneBy({
firstName: "Timber",
lastName: "Saw",
})
Columnas especiales
Existen varios tipos de columnas especiales con funcionalidad adicional:
-
@CreateDateColumnes una columna especial que se establece automáticamente a la fecha de inserción de la entidad. No necesitas establecer esta columna; se configurará automáticamente. -
@UpdateDateColumnes una columna especial que se actualiza automáticamente con la hora de modificación de la entidad cada vez que llamas asavedel EntityManager o Repository, o durante operacionesupsertcuando ocurre una actualización. No necesitas establecer esta columna; se configurará automáticamente. -
@DeleteDateColumnes una columna especial que se establece automáticamente a la hora de eliminación de la entidad cada vez que llamas al soft-delete del EntityManager o Repository. No necesitas establecer esta columna; se configurará automáticamente. Si @DeleteDateColumn está configurado, el ámbito predeterminado será "non-deleted". -
@VersionColumnes una columna especial que se actualiza automáticamente al número de versión de la entidad (incremental) cada vez que llamas asavedel EntityManager o Repository, o durante operacionesupsertcuando ocurre una actualización. No necesitas establecer esta columna; se configurará automáticamente.
Tipos de columna
TypeORM soporta todos los tipos de columna más comunes compatibles con bases de datos. Los tipos de columna son específicos de cada base de datos, lo que brinda mayor flexibilidad en el diseño de tu esquema.
Puedes especificar el tipo de columna como primer parámetro de @Column
o en las opciones de columna de @Column, por ejemplo:
@Column("int")
o
@Column({ type: "int" })
Si deseas especificar parámetros de tipo adicionales, puedes hacerlo mediante las opciones de columna. Por ejemplo:
@Column("varchar", { length: 200 })
Nota sobre el tipo
bigint: el tipo de columnabigint, usado en bases de datos SQL, no encaja en el tiponumberregular y asigna la propiedad a unstring.
Tipo de columna enum
El tipo de columna enum es compatible con postgres y mysql. Existen varias definiciones posibles:
Usando enums de TypeScript:
export enum UserRole {
ADMIN = "admin",
EDITOR = "editor",
GHOST = "ghost",
}
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number
@Column({
type: "enum",
enum: UserRole,
default: UserRole.GHOST,
})
role: UserRole
}
Nota: Se admiten enums de tipo string, numéricos y heterogéneos.
Usando arrays con valores de enum:
export type UserRoleType = "admin" | "editor" | "ghost",
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column({
type: "enum",
enum: ["admin", "editor", "ghost"],
default: "ghost"
})
role: UserRoleType
}
simple-array tipo de columna
Tipo de columna simple-array
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number
@Column("simple-array")
names: string[]
}
const user = new User()
user.names = ["Alexander", "Alex", "Sasha", "Shurik"]
Se almacenará en una columna de base de datos como Alexander,Alex,Sasha,Shurik.
Al cargar datos desde la base, los nombres se devolverán como un array, igual que se almacenaron.
Ten en cuenta que NO DEBES incluir comas en los valores que escribas.
Tipo de columna simple-json
El tipo simple-json puede almacenar cualquier valor serializable mediante JSON.stringify.
Es muy útil cuando tu base de datos no soporta tipo JSON nativo y quieres almacenar objetos sin complicaciones.
Por ejemplo:
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number
@Column("simple-json")
profile: { name: string; nickname: string }
}
const user = new User()
user.profile = { name: "John", nickname: "Malkovich" }
Se almacenará como {"name":"John","nickname":"Malkovich"} en una columna.
Al cargar datos, recuperarás tu objeto/array/primitivo mediante JSON.parse.
Columnas con valores generados
Puedes crear columnas con valores generados utilizando el decorador @Generated. Por ejemplo:
@Entity()
export class User {
@PrimaryColumn()
id: number
@Column()
@Generated("uuid")
uuid: string
}
El valor uuid se generará automáticamente y se almacenará en la base de datos.
Además de "uuid", existen otros tipos generados: "increment", "identity" (solo para Postgres 10+) y "rowid" (solo para CockroachDB). Sin embargo, existen limitaciones en algunas plataformas de bases de datos con este tipo de generación (por ejemplo, algunas bases de datos solo permiten una columna autoincremental, o requieren que sea clave primaria).
Columnas vectoriales
Las columnas vectoriales son compatibles en MariaDB/MySQL, Microsoft SQL Server, PostgreSQL (mediante la extensión pgvector) y SAP HANA Cloud, permitiendo almacenar y consultar incrustaciones vectoriales para búsqueda de similitud y aplicaciones de aprendizaje automático.
TypeORM soporta los tipos de columna vector y halfvec en diferentes bases de datos:
-
vector- almacena vectores como floats de 4 bytes (precisión simple)- MariaDB/MySQL: tipo nativo
vector - Microsoft SQL Server: tipo nativo
vector - PostgreSQL: tipo
vector, disponible mediante extensiónpgvector - SAP HANA Cloud: alias para tipo
real_vector
- MariaDB/MySQL: tipo nativo
-
halfvec- almacena vectores como floats de 2 bytes (media precisión) para eficiencia de memoria- PostgreSQL: tipo
halfvec, disponible mediante extensiónpgvector - SAP HANA Cloud: alias para tipo
half_vector
- PostgreSQL: tipo
Puedes especificar el número de dimensiones del vector usando la opción length:
@Entity()
export class Post {
@PrimaryGeneratedColumn()
id: number
// Vector without specified dimensions
@Column("vector")
embedding: number[] | Buffer
// Vector with 3 dimensions: vector(3)
@Column("vector", { length: 3 })
embedding_3d: number[] | Buffer
// Half-precision vector with 4 dimensions: halfvec(4) (works on PostgreSQL and SAP HANA only)
@Column("halfvec", { length: 4 })
halfvec_embedding: number[] | Buffer
}
Nota:
- MariaDB/MySQL: Los vectores son compatibles desde MariaDB 11.7 y MySQL 9
- Microsoft SQL Server: El soporte para tipo vector requiere SQL Server 2025 (17.x) o superior.
- PostgreSQL: Las columnas vectoriales requieren la extensión
pgvectorinstalada. Esta extensión proporciona los tipos de datos vectoriales y operadores de similitud.- SAP HANA: Las columnas vectoriales requieren SAP HANA Cloud (2024Q1+) y una versión compatible de
@sap/hana-client.
Columnas espaciales
Microsoft SQLServer, MySQL/MariaDB, PostgreSQL/CockroachDB y SAP HANA admiten columnas espaciales. El soporte de TypeORM varía ligeramente entre bases de datos, particularmente porque los nombres de columna difieren entre plataformas.
MS SQL, MySQL/MariaDB y SAP HANA usan geometrías en formato well-known text (WKT), por lo que las columnas de geometría deben marcarse con el tipo string.
import { Entity, PrimaryColumn, Column } from "typeorm"
@Entity()
export class Thing {
@PrimaryColumn()
id: number
@Column("point")
point: string
@Column("linestring")
linestring: string
}
...
const thing = new Thing()
thing.point = "POINT(1 1)"
thing.linestring = "LINESTRING(0 0,1 1,2 2)"
Para Postgres/CockroachDB, consulta Tipos de datos Postgis
Opciones de columna
Las opciones de columna definen configuraciones adicionales para las columnas de tu entidad. Puedes especificarlas en @Column:
@Column({
type: "varchar",
length: 150,
unique: true,
// ...
})
name: string;
Lista de opciones disponibles en ColumnOptions:
-
type: ColumnType- Tipo de columna. Uno de los tipos listados arriba. -
name: string- Nombre de la columna en la tabla de base de datos. Por defecto, el nombre se genera a partir de la propiedad. Puedes cambiarlo especificando tu propio nombre. -
length: number- Longitud del tipo de columna. Por ejemplo, para crear un tipovarchar(150)especificas el tipo de columna y la opción de longitud. -
onUpdate: string- DisparadorON UPDATE. Solo se usa en MySQL. -
nullable: boolean- Define si la columna esNULLoNOT NULLen la base de datos. Por defecto esnullable: false. -
update: boolean- Indica si el valor de la columna se actualiza con la operación "save". Si es false, podrás escribir este valor solo al insertar el objeto por primera vez. Valor predeterminado:true. -
insert: boolean- Indica si el valor de la columna se establece al insertar el objeto por primera vez. Valor predeterminado:true. -
select: boolean- Define si esta columna se oculta por defecto en las consultas. Cuando esfalse, los datos no aparecerán en consultas estándar. Por defecto esselect: true. -
default: string- Establece un valorDEFAULTa nivel de base de datos para la columna. -
primary: boolean- Marca la columna como primaria. Equivalente a usar@PrimaryColumn. -
unique: boolean- Marca la columna como única (crea una restricción UNIQUE). -
comment: string- Comentario de la columna en la base de datos. No compatible con todos los tipos de bases. -
precision: number- Precisión para columnas decimales (numéricas exactas), que define la cantidad máxima de dígitos almacenados. Aplica solo para ciertos tipos de columna. -
scale: number- Escala para columnas decimales (numéricas exactas), que representa los dígitos a la derecha del punto decimal. No puede exceder la precisión. Aplica solo para ciertos tipos de columna. -
unsigned: boolean- Añade el atributoUNSIGNEDa columnas numéricas. Solo para MySQL. -
charset: string- Define el charset de la columna. No compatible con todos los tipos de bases. -
collation: string- Define la collation de la columna. -
enum: string[]|AnyEnum- Para columnasenum, especifica los valores permitidos. Puede ser un array o una clase enum. -
enumName: string- Define el nombre para el enum utilizado. -
asExpression: string- Expresión para columnas generadas. Solo para MySQL. -
generatedType: "VIRTUAL"|"STORED"- Tipo de columna generada. Solo para MySQL. -
hstoreType: "object"|"string"- Tipo de retorno para columnasHSTORE. Devuelve el valor como string u objeto. Solo para Postgres. -
array: boolean- Para tipos de columna que pueden ser arrays en Postgres/CockroachDB (ej: int[]). -
transformer: { from(value: DatabaseType): EntityType, to(value: EntityType): DatabaseType }- Transforma propiedades entre el tipo de entidadEntityTypey el tipo de baseDatabaseType. Soporta arrays de transformers que se aplican en orden al escribir y en reverso al leer. Ej:[lowercase, encrypt]aplica minúsculas y luego encripta al escribir; desencripta al leer. -
utc: boolean- Si los valores de fecha deben almacenarse/recuperarse en UTC en lugar de zona horaria local. Solo aplica a columnasdate. Valor predeterminado:false(mantiene compatibilidad con comportamiento anterior).
Nota: la mayoría de estas opciones son específicas de RDBMS y no están disponibles en MongoDB.
Herencia de entidades
Puedes reducir duplicación de código mediante herencia de entidades.
Por ejemplo, tienes las entidades Photo, Question y Post:
@Entity()
export class Photo {
@PrimaryGeneratedColumn()
id: number
@Column()
title: string
@Column()
description: string
@Column()
size: string
}
@Entity()
export class Question {
@PrimaryGeneratedColumn()
id: number
@Column()
title: string
@Column()
description: string
@Column()
answersCount: number
}
@Entity()
export class Post {
@PrimaryGeneratedColumn()
id: number
@Column()
title: string
@Column()
description: string
@Column()
viewCount: number
}
Como ves, todas comparten columnas: id, title, description. Para reducir duplicación puedes crear una clase base Content:
export abstract class Content {
@PrimaryGeneratedColumn()
id: number
@Column()
title: string
@Column()
description: string
}
@Entity()
export class Photo extends Content {
@Column()
size: string
}
@Entity()
export class Question extends Content {
@Column()
answersCount: number
}
@Entity()
export class Post extends Content {
@Column()
viewCount: number
}
Todas las columnas (relaciones, incrustaciones, etc.) de las entidades padre (el padre también puede extender otra entidad) se heredarán y crearán en las entidades finales.
Entidades jerárquicas (árbol)
TypeORM soporta patrones de Lista de Adyacencia y Tabla de Clausura para estructuras jerárquicas.
Lista de adyacencia
La lista de adyacencia es un modelo simple con autoreferencias. Su ventaja es la simplicidad; su desventaja es la imposibilidad de cargar árboles grandes de una vez debido a limitaciones de joins. Ejemplo:
import {
Entity,
Column,
PrimaryGeneratedColumn,
ManyToOne,
OneToMany,
} from "typeorm"
@Entity()
export class Category {
@PrimaryGeneratedColumn()
id: number
@Column()
name: string
@Column()
description: string
@ManyToOne((type) => Category, (category) => category.children)
parent: Category
@OneToMany((type) => Category, (category) => category.parent)
children: Category[]
}
Tabla de clausura
Una tabla de clausura almacena relaciones padre-hijo en una tabla separada de forma optimizada. Es eficiente tanto en lectura como escritura. Para más detalles, revisa esta excelente presentación de Bill Karwin. Ejemplo:
import {
Entity,
Tree,
Column,
PrimaryGeneratedColumn,
TreeChildren,
TreeParent,
TreeLevelColumn,
} from "typeorm"
@Entity()
@Tree("closure-table")
export class Category {
@PrimaryGeneratedColumn()
id: number
@Column()
name: string
@Column()
description: string
@TreeChildren()
children: Category[]
@TreeParent()
parent: Category
@TreeLevelColumn()
level: number
}