What is SQL to MikroORM Entity Converter?
MikroORM is a TypeScript ORM for Node.js built on the Data Mapper pattern, Unit of Work, and Identity Map — three architectural concepts borrowed from Martin Fowler's enterprise design patterns. Unlike Active Record ORMs where model classes contain persistence logic, MikroORM separates entity definitions from the data access layer: entities are plain TypeScript classes decorated with @Entity, @Property, and @PrimaryKey, while a dedicated EntityManager handles all database operations. The Unit of Work tracks every loaded entity and computes the minimal set of SQL statements needed on flush(), and the Identity Map guarantees that querying the same row twice returns the same object reference. This converter reads your CREATE TABLE statements and generates MikroORM entity classes with the correct decorator configuration — including @ManyToOne for foreign key references, autoincrement flags for SERIAL columns, nullable options, and dialect-specific columnType annotations that ensure the schema matches your actual database.
How to Use
- Select your target database dialect — PostgreSQL, MySQL, or SQLite — so the converter emits the correct driver import and columnType values
- Paste one or more CREATE TABLE statements into the SQL input area
- Click "Generate MikroORM Entity" to produce TypeScript entity classes with @Entity, @Property, @PrimaryKey, and @ManyToOne decorators
- Copy the output into your MikroORM project and register the entities in your ORM configuration
- Add @OneToMany decorators on the reverse side of foreign key relationships to enable bidirectional navigation
Why Use This Tool?
Tips & Best Practices
- After generating entities, add @OneToMany(() => CommentEntity, c => c.post) on the parent side to complete bidirectional relationships
- Use the nullable: true option on @ManyToOne properties to match optional foreign keys — the converter handles this automatically for columns without NOT NULL
- For JSONB columns, replace the generated any type with a typed interface and add a customType property for serialization control
- MikroORM requires you to register every entity in the MikroORM.init() configuration — unregistered entities will not be discovered at runtime
Frequently Asked Questions
How does MikroORM map SQL types to TypeScript property types?
Integer-family SQL types (INTEGER, BIGINT, SERIAL) map to number; string types (VARCHAR, TEXT, CHAR) map to string; BOOLEAN maps to boolean; TIMESTAMP and DATE map to Date; JSON and JSONB map to any; UUID maps to string; BLOB and BYTEA map to Buffer. Each property also receives a columnType annotation (e.g., columnType: 'varchar', columnType: 'timestamptz') so MikroORM generates the correct DDL during schema synchronization.
When should I NOT use MikroORM?
Skip MikroORM if you prefer a query-builder-only approach without change tracking — Kysely or Knex are lighter alternatives. MikroORM's Unit of Work adds memory overhead for large result sets, and its decorator-based metadata requires either reflect-metadata or ts-morph, which may conflict with certain build pipelines. For simple CRUD microservices, a thin query builder often suffices.
How does the Data Mapper pattern differ from Active Record?
In Active Record (e.g., TypeORM with ActiveRecord mode), entity classes extend a base class and call save() on themselves. In Data Mapper, entities are plain objects with no persistence methods — a separate EntityManager persists them. This separation makes entities portable across different persistence contexts and easier to unit-test without mocking the database.
What does the Unit of Work actually do?
The Unit of Work tracks every entity loaded during a request. When you call em.flush(), it compares each tracked entity's current state against its original snapshot and generates only the SQL statements needed to persist the changes — batching multiple updates into a single transaction without you writing explicit INSERT or UPDATE calls.
Is my SQL data sent to a server?
No. All parsing and entity generation runs entirely in your browser. Your SQL schema never leaves your device, and no network requests are made during the conversion process.
How do I handle many-to-many relationships?
The converter generates @ManyToOne for REFERENCES constraints. For many-to-many relationships, create a junction table (e.g., user_roles) and the converter will produce two @ManyToOne properties. You can then add @ManyToMany decorators on both parent entities pointing to the junction table, using the pivotEntity option for explicit control.
Real-world Examples
User accounts with unique email and default timestamp
A users table with SERIAL primary key, unique email constraint, and default values for boolean and timestamp columns, converted to a MikroORM entity class.
CREATE TABLE users ( id SERIAL PRIMARY KEY, email VARCHAR(255) UNIQUE NOT NULL, display_name VARCHAR(100) NOT NULL, is_active BOOLEAN DEFAULT true, created_at TIMESTAMP DEFAULT NOW() );
import { Entity, PrimaryKey, Property } from '@mikro-orm/core';
import { PostgreSqlDriver } from '@mikro-orm/postgresql';
@Entity({ tableName: 'users' })
export class Users {
@PrimaryKey({ autoincrement: true })
id!: number;
@Property({ columnType: 'varchar', unique: true })
email!: string;
@Property({ columnType: 'varchar', length: 100 })
displayName!: string;
@Property({ columnType: 'boolean', default: true })
isActive!: boolean;
@Property({ columnType: 'timestamp', default: () => new Date() })
createdAt!: Date;
}Blog posts with foreign key to author
A posts table with a foreign key referencing the users table, demonstrating how REFERENCES constraints become @ManyToOne decorators with the referenced entity type.
CREATE TABLE users ( id SERIAL PRIMARY KEY, name VARCHAR(100) NOT NULL ); CREATE TABLE posts ( id SERIAL PRIMARY KEY, title VARCHAR(255) NOT NULL, body TEXT, author_id INTEGER NOT NULL REFERENCES users(id), published BOOLEAN DEFAULT false, created_at TIMESTAMP DEFAULT NOW() );
import { Entity, PrimaryKey, Property, ManyToOne } from '@mikro-orm/core';
import { PostgreSqlDriver } from '@mikro-orm/postgresql';
@Entity({ tableName: 'users' })
export class Users {
@PrimaryKey({ autoincrement: true })
id!: number;
@Property({ columnType: 'varchar', length: 100 })
name!: string;
}
@Entity({ tableName: 'posts' })
export class Posts {
@PrimaryKey({ autoincrement: true })
id!: number;
@Property({ columnType: 'varchar' })
title!: string;
@Property({ columnType: 'text', nullable: true })
body!: string | null;
@ManyToOne({ entity: () => Users, fieldName: 'author_id' })
author!: Users;
@Property({ columnType: 'boolean', default: false })
published!: boolean;
@Property({ columnType: 'timestamp', default: () => new Date() })
createdAt!: Date;
}