Relaciones
Builders
Sección titulada «Builders»jsorm usa builders de relaciones explícitos que describen la relación SQL exacta entre dos modelos. Cada builder genera el SQL de join y mutación apropiado sin eager loading oculto ni lazy proxies.
Builders de relaciones
Sección titulada «Builders de relaciones»| Builder | Relación SQL | Cuándo usar |
|---|---|---|
t.belongsTo(Model) | Foreign key en esta tabla | User tiene columna roleId |
t.hasOne(Model) | Foreign key en otra tabla | Profile tiene columna userId |
t.hasMany(Model) | Foreign key en otra tabla | Post tiene columna authorId |
t.manyToMany(Model) | Tabla de unión | Posts ↔ Tags via post_tags |
Ejemplo
Sección titulada «Ejemplo»import { defineModel, t } from 'jsorm';
const Role = defineModel('roles', { id: t.number().primary(), name: t.string().unique(),});
const Profile = defineModel('profiles', { id: t.number().primary(), bio: t.string().optional(),});
const Tag = defineModel('tags', { id: t.number().primary(), name: t.string().unique(),});
const Post = defineModel('posts', { id: t.number().primary(), title: t.string(), // Nombre de tabla de unión inferido desde config de naming (por defecto: alfabético) tags: t.manyToMany(Tag), // O especifica tabla de unión y columnas FK explícitamente: // tags: t.manyToMany(Tag, { // through: 'post_tags', // throughLocalKey: 'post_id', // throughForeignKey: 'tag_id', // }),});
const User = defineModel('users', { id: t.number().primary(), name: t.string(), role: t.belongsTo(Role, { onUpdate: 'cascade', onDelete: 'restrict', constraintName: 'fk_users_role_id', // nombre explícito de restricción FK }).index(), profile: t.hasOne(Profile), posts: t.hasMany(Post),});Seleccionar relaciones
Sección titulada «Seleccionar relaciones»Incluye relaciones en select para cargarlas como objetos anidados:
const users = await jsorm.get(User, { select: { id: true, name: true, role: { name: true }, profile: { bio: true }, posts: { title: true, tags: { name: true }, }, },});// Tipado: Array<{ id: number; name: string; role: { name: string }; ... }>Filtrar a través de relaciones
Sección titulada «Filtrar a través de relaciones»Usa where anidado para filtrar por campos de relaciones:
const admins = await jsorm.get(User, { select: { name: true }, where: { role: { name: { eq: 'admin' } }, posts: { title: { contains: 'release' } }, },});Mutaciones de relaciones
Sección titulada «Mutaciones de relaciones»Conectar a un registro existente
Sección titulada «Conectar a un registro existente»await jsorm.update(User, { data: { role: { connect: 1 }, }, where: { id: 5 },});Crear y conectar
Sección titulada «Crear y conectar»await jsorm.update(User, { data: { profile: { create: { bio: 'Builder from Day 1' }, }, }, where: { id: 5 },});Many-to-many connect y disconnect
Sección titulada «Many-to-many connect y disconnect»await jsorm.update(Post, { data: { tags: { connect: [1, 2, 3], disconnect: [4], }, }, where: { id: 10 },});Ejemplo completo con mutación mixta
Sección titulada «Ejemplo completo con mutación mixta»await jsorm.insert(User, { name: 'Alice', role: { connect: 1 }, profile: { create: { bio: 'Builder' }, }, posts: { create: [ { title: 'First post', tags: { connect: [1, 2] } }, ], },});Opciones de integridad referencial
Sección titulada «Opciones de integridad referencial»Configura onUpdate y onDelete en belongsTo para controlar la integridad referencial a nivel de base de datos:
role: t.belongsTo(Role, { onUpdate: 'cascade', // 'cascade' | 'restrict' | 'set-null' | 'no-action' onDelete: 'restrict',}),Buenas prácticas
Sección titulada «Buenas prácticas»- Usa el builder de relación que coincida con la forma real de los datos — no uses
hasManycuando la relación esmanyToMany. - Configura
onUpdateyonDeleteintencionalmente en lugar de depender de los defaults de la base de datos. - Mantén las mutaciones de relaciones cerca de las operaciones de escritura en lugar de dispersar la lógica de pivot manualmente.
- Siempre incluye campos de relaciones explícitamente en
select— jsorm nunca carga relaciones implícitamente.