What is mikro-orm?
Mikro-ORM is a TypeScript ORM for Node.js based on Data Mapper, Unit of Work, and Identity Map patterns. It supports multiple databases including MongoDB, MySQL, PostgreSQL, SQLite, and MariaDB. It provides a powerful and flexible way to interact with your database using TypeScript and JavaScript.
What are mikro-orm's main functionalities?
Entity Definition
Defines an entity with properties that map to database columns. The `@Entity` decorator marks the class as a database entity, while `@PrimaryKey` and `@Property` decorators define the primary key and other properties respectively.
```typescript
import { Entity, PrimaryKey, Property } from 'mikro-orm';
@Entity()
class User {
@PrimaryKey()
id!: number;
@Property()
name!: string;
@Property()
email!: string;
}
```
CRUD Operations
Demonstrates basic Create, Read, Update, and Delete (CRUD) operations. The `persistAndFlush` method saves a new entity to the database, and the `find` method retrieves entities from the database.
```typescript
const user = new User();
user.name = 'John Doe';
user.email = 'john.doe@example.com';
await orm.em.persistAndFlush(user);
const users = await orm.em.find(User, {});
console.log(users);
```
Query Builder
Shows how to use the query builder to construct and execute complex queries. The `createQueryBuilder` method creates a new query builder instance, and the `select` and `where` methods build the query.
```typescript
const qb = orm.em.createQueryBuilder(User);
const users = await qb.select('*').where({ name: 'John Doe' }).execute();
console.log(users);
```
Transactions
Illustrates how to perform operations within a transaction. The `transactional` method ensures that all operations within the callback are executed within a single transaction.
```typescript
await orm.em.transactional(async em => {
const user = new User();
user.name = 'Jane Doe';
user.email = 'jane.doe@example.com';
await em.persistAndFlush(user);
});
```
Other packages similar to mikro-orm
typeorm
TypeORM is another TypeScript ORM for Node.js that supports Active Record and Data Mapper patterns. It is highly popular and supports multiple databases. Compared to Mikro-ORM, TypeORM has a larger community and more extensive documentation, but Mikro-ORM offers a more modern and flexible API.
sequelize
Sequelize is a promise-based Node.js ORM for Postgres, MySQL, MariaDB, SQLite, and Microsoft SQL Server. It is known for its simplicity and ease of use. While Sequelize is more mature and has a larger user base, Mikro-ORM provides better TypeScript support and more advanced features like Unit of Work and Identity Map patterns.
objection
Objection.js is an SQL-friendly ORM for Node.js, built on top of the SQL query builder Knex.js. It aims to stay as close to the SQL syntax as possible while providing a powerful and flexible API. Compared to Mikro-ORM, Objection.js offers more control over raw SQL queries but lacks some of the higher-level abstractions and features provided by Mikro-ORM.
mikro-orm
Simple typescript mongo ORM for node.js based on data-mapper, unit-of-work and identity-map patterns.
Heavily inspired by doctrine.
![Coverage Status](https://img.shields.io/coveralls/B4nan/mikro-orm.svg)
Defining entity
import { BaseEntity, Entity, ManyToOne, Property } from 'mikro-orm';
import { Publisher } from './Publisher';
import { Author } from './Author';
import { BookRepository } from './BookRepository';
@Entity({ collection: 'books-table', customRepository: BookRepository })
export class Book extends BaseEntity {
@Property()
title: string;
@ManyToOne({ entity: () => Author.name })
author: Author;
@ManyToOne({ entity: () => Publisher.name })
publisher: Publisher;
@Property()
metaObject: object;
@Property()
metaArray: any[];
@Property()
metaArrayOfStrings: string[];
constructor(title: string, author: Author) {
super();
this.title = title;
this.author = author;
this.metaObject = {};
this.metaArray = [{test: 123, lol: true}];
this.metaArrayOfStrings = ['test'];
}
}
Installation
$ yarn add mikro-orm
or
$ npm install mikro-orm
Usage
For more examples, take a look at tests/EntityManager.test.ts
.
import { MikroORM, Collection } from 'mikro-orm';
import { Author } from './entities/Author';
import { Published } from './entities/Published';
import { Book } from './entities/Book';
const orm = await MikroORM.init({
entitiesDirs: ['entities'],
dbName: 'my-db-name',
baseDir: __dirname,
});
const author = new Author('Jon Snow', 'snow@wall.st');
author.born = new Date();
const publisher = new Publisher('7K publisher');
const book1 = new Book('My Life on The Wall, part 1', author);
book1.publisher = publisher;
const book2 = new Book('My Life on The Wall, part 2', author);
book2.publisher = publisher;
const book3 = new Book('My Life on The Wall, part 3', author);
book3.publisher = publisher;
await orm.em.persist(book1, false);
await orm.em.persist(book2, false);
await orm.em.persist(book3);
const authorRepository = orm.em.getRepository<Author>(Author.name);
const jon = await authorRepository.findOne({ name: 'Jon Snow' }, ['books']);
const authors = await authorRepository.findAll(['books']);
console.log(jon === authors[0]);
for (const author of authors) {
console.log(author.name);
for (const book of author.books) {
console.log(book.title);
console.log(book.author.isInitialized());
console.log(book.author.id);
console.log(book.author.name);
console.log(book.publisher);
console.log(book.publisher.isInitialized());
console.log(book.publisher.id);
console.log(book.publisher.name);
}
}
const booksRepository = orm.em.getRepository<Author>(Author.name);
const books = await booksRepository.find({ author: jon.id }, [], { title: -1 }, 2, 1);
console.log(books);
TODO
- cascade persist in collections
- aggregate support?
- improve populating in EM#find() method
- rehydrate and populate missing references when fetching already loaded entities from db
- add nativeUpdate and nativeDelete (without hooks support), allow only entities in EM#remove
- remove references on other entities when deleting entity (e.g. from M:N collection)
- support for string ids in find query
TODO docs
- 1:M / M:1 collections
- many to many collections
- custom repository
- cascading
- identity map
- lifecycle hooks