Please support a project by simply putting a Github star. Share this library with friends on Twitter and everywhere else you can.
ORM is in active development, but main API is pretty stable. If you notice bug or have something not working please report an issue, we'll try to fix it as soon as possible. More documentation and features expected to be soon. Feel free to contribute.
For the latest release changes see changelog.
TypeORM is an Object Relational Mapper (ORM) for Node.js written in TypeScript that can be used with TypeScript or JavaScript (ES5, ES6, ES7). Its goal to always support latest JavaScript features and provide features that help you to develop any kind of applications that use database - from small applications with a few tables to large scale enterprise applications. TypeORM helps you to:
- automatically create in the database table schemas based on your models
- ability to transparently insert / update / delete to the database your objects
- map your selections from tables to javascript objects and map table columns to javascript object's properties
- create one-to-one, many-to-one, one-to-many, many-to-many relations between tables
- and much more...
TypeORM uses Data Mapper pattern, unlike all other JavaScript ORMs that currently exist, which means you can write loosely coupled, scalable, maintainable applications with less problems.
The benefit of using TypeORM for the programmer is the ability to focus on the business logic and worry about persistence only as a secondary problem.
TypeORM is highly influenced by other ORMs, such as Hibernate, Doctrine and Entity Framework.
Installation
-
Install module:
npm install typeorm --save
-
You need to install
reflect-metadata
shim:npm install reflect-metadata --save
and import it somewhere in the global place of your app (for example in
app.ts
):import "reflect-metadata";
-
You may need to install node typings:
npm install @types/node --save
-
Install database driver:
-
for MySQL or MariaDB
npm install mysql --save
-
for PostgreSQL
npm install pg --save
-
for SQLite
npm install sqlite3 --save
-
for Microsoft SQL Server
npm install mssql --save
-
for Oracle (experimental)
npm install oracledb --save
Install only one of them, depend on which database you use.
To make oracle driver to work you need to follow installation instructions from their site.
-
TypeScript configuration
Also make sure you are using TypeScript compiler version > 2.1 and you have enabled following settings in tsconfig.json
:
"emitDecoratorMetadata": true,"experimentalDecorators": true,
You'll also need to enable es6
in the lib
section of compiler options, or install es6-shim
from @types
.
Node.js version
TypeORM was tested with Node.js version 4 and above. If you have errors during app bootstrap, try to upgrade your Node.js version to the latest version.
Usage in the browser with WebSQL (experimental)
TypeORM works in the browser and has experimental support of WebSQL.
If you want to use TypeORM in the browser then you need to npm i typeorm-browser
instead of typeorm
.
More information about it in this page.
Also take a look on this sample.
Quick Start
In TypeORM tables are created from Entities.
Entity is your model decorated by a @Entity
decorator.
You can get entities from the database and insert/update/remove them from there.
Let's say we have a model entity/Photo.ts
:
id: number; name: string; description: string; fileName: string; views: number;
Creating entity
Now let's make it entity:
; @ id: number; name: string; description: string; fileName: string; views: number; isPublished: boolean;
Add table columns
Now we have a table, and each table consist of columns.
Let's add some columns.
You can make any property of your model a column by using a @Column
decorator:
; @ @ id: number; @ name: string; @ description: string; @ fileName: string; @ views: number; @ isPublished: boolean;
Create a primary column
Perfect.
Now ORM will generate us a photo table with all its properties as columns.
But there is one thing left.
Each entity must have a primary column.
This is requirement and you can't avoid it.
To make a column a primary you need to use @PrimaryColumn
decorator.
; @ @ id: number; @ name: string; @ description: string; @ fileName: string; @ views: number; @ isPublished: boolean;
Create auto-increment / generated / sequence / identity column
Now, let's say you want to make your id column to be auto-generated (this is known as auto-increment / sequence / generated identity column).
To do that you need to change your column's type to integer and set a { generated: true }
in your primary column's options:
; @ @ id: number; @ name: string; @ description: string; @ fileName: string; @ views: number; @ isPublished: boolean;
@PrimaryGeneratedColumn
decorator
Using Now your photo's id will always be a generated, auto increment value.
Since this is a common task - to create a generated auto increment primary column,
there is a special decorator called @PrimaryGeneratedColumn
to do the same.
Let's use it instead:
; @ @ id: number; @ name: string; @ description: string; @ fileName: string; @ views: number; @ isPublished: boolean;
Custom column data types
Next step, let's fix our data types. By default, string is mapped to a varchar(255)-like type (depend of database type). Number is mapped to a float/double-like type (depend of database type). We don't want all our columns to be limited varchars or excessive floats. Let's setup correct data types:
; @ @ id: number; @ name: string; @ description: string; @ fileName: string; @ views: number; @ isPublished: boolean;
Creating connection with the database
Now, when our entity is created, let's create app.ts
file and setup our connection there:
;;; ;
We are using MySQL in this example, but you can use any other database. To use another database simply change type in the driver options to the database type you are using: mysql, mariadb, postgres, sqlite, mssql or oracle. Also make sure to use your own host, port, username, password and database settings.
We added our Photo entity to the list of entities for this connection. Each entity you are using in your connection must be listed here.
Setting autoSchemaSync
makes sure your entities will be synced with the database, every time you run the application.
Loading all entities from the directory
Later, when we create more entities we need to add them to the entities in our configuration. But this is not very convenient, and instead we can setup the whole directory, where from all entities will be connected and used in our connection:
; ;
Run the application
Now you if run your app.ts
, connection with database will be initialized and database table for your Photo will be created.
+-------------+--------------+----------------------------+| photo |+-------------+--------------+----------------------------+| id | int | PRIMARY KEY AUTO_INCREMENT || name | varchar | || description | text | || filename | varchar | || views | int | || isPublished | boolean | |+-------------+--------------+----------------------------+
Creating and inserting photo into the database
Now let's create a new photo to save it in the database:
; ;
Using async/await syntax
Let's use latest TypeScript advantages and use async/await syntax instead:
;; ;
Using Entity Manager
We just created a new photo and saved it in the database.
We used EntityManager
to save it.
Using entity managers you can manipulate any entity in your app.
Now let's load our saved entity:
;; ;
savedPhotos will be an array of Photo objects with the data loaded from the database.
Using Repositories
Now let's refactor our code and use Repository
instead of EntityManager.
Each entity has its own repository which handles all operations with its entity.
When you deal with entities a lot, Repositories are more convenient to use then EntityManager:
;; ;
Loading photos from the database
Let's try more load operations using Repository:
;; ;
Updating photo in the database
Now let's load a single photo from the database, update it and save it:
;; ;
Now photo with id = 1
will be updated in the database.
Removing photo from the database
Now let's remove our photo from the database:
;; ;
Now photo with id = 1
will be removed from the database.
Creating a one-to-one relation
Let's create a one-to-one relation with another class.
Let's create a new class called PhotoMetadata.ts
which will contain a PhotoMetadata class which supposed to contain our photo's additional meta-information:
;; @ @ id: number; @ height: number; @ width: number; @ orientation: string; @ compressed: boolean; @ comment: string; @ @ photo: Photo;
Here, we are used a new decorator called @OneToOne
. It allows to create one-to-one relations between two entities.
type => Photo
is a function that returns the class of the entity with which we want to make our relation.
We are forced to use a function that returns a class, instead of using class directly, because of the language specifics.
We can also write it as a () => Photo
, but we use type => Photo as convention to increase code readability.
Type variable itself does not contain anything.
We also put @JoinColumn
decorator, which indicates that this side of the relationship will be owning relationship.
Relations can be a unidirectional and bidirectional.
Only one side of relational can be owner.
Using this decorator is required on owner side of the relationship.
If you run the app you'll see a new generated table, and it will contain a column with a foreign key for the photo relation:
+-------------+--------------+----------------------------+| photometadata |+-------------+--------------+----------------------------+| id | int | PRIMARY KEY AUTO_INCREMENT || height | int | || width | int | || comment | varchar | || compressed | boolean | || orientation | varchar | || photo | int | FOREIGN KEY |+-------------+--------------+----------------------------+
Persisting an object with one-to-one relation
Now let's save a photo, its metadata and attach them to each other.
;;; ;
Adding inverse side of a relation
Relations can be a unidirectional and bidirectional. Now, relation between PhotoMetadata and Photo is unidirectional. Owner of the relation is PhotoMetadata and Photo doesn't know anything about PhotoMetadata. This makes complicated accessing a photo metadata from the photo objects. To fix it we should add inverse relation and make relations between PhotoMetadata and Photo bidirectional. Let's modify our entities:
;; @ /* ... other columns */ @ @ photo: Photo;
;; @ /* ... other columns */ @ metadata: PhotoMetadata;
photo => photo.metadata
is a function that returns a name of the inverse side of the relation.
Here we show that metadata property of the Photo class is where we store PhotoMetadata in the Photo class.
You could also instead of passing function that returns a property of the photo simply pass a string to @OneToOne
decorator, like "metadata"
.
But we used this function-typed approach to make your refactorings easier.
Note that we should use @JoinColumn
only on one side of relation.
On which side you put this decorator, that side will be owning side of relationship.
Owning side of relationship contain a column with a foreign key in the database.
Loading object with their relations
Now let's load our photo, and its photo metadata in a single query.
There are two ways to do it - one you can use FindOptions
, second is to use QueryBuilder.
Let's use FindOptions first.
Repository.find
method allows you to specify object with FindOptions interface.
Using this you can customize your query to perform more complex queries.
;;; ;
Here photos will contain array of photos from the database, and each photo will contain its photo metadata.
alias
is a required property of FindOptions. Its your own alias name of the data you are selecting.
You'll use this alias in your where, order by, group by, join and other expressions.
We also used innerJoinAndSelect
to inner and join and select the data from photo.metadata.
In "photo.metadata"
"photo" is an alias you used, and "metadata" is a property name with relation of the object you are selecting.
"metadata"
: is a new alias to the data returned by join expression.
Let's use QueryBuilder
for the same purpose. QueryBuilder allows to use more complex queries in an elegant way:
;;; ;
Using cascade options to automatically save related objects
We can setup cascade options in our relations, in the cases when we want our related object to be persisted whenever other object is saved.
Let's change our photo's @OneToOne
decorator a bit:
/// ... other columns @ metadata: PhotoMetadata;
- cascadeInsert - automatically insert metadata in the relation if it does not exist in its table. This means that we don't need to manually insert a newly created photoMetadata object.
- cascadeUpdate - automatically update metadata in the relation if in this object something is changed.
- cascadeRemove - automatically remove metadata from its table if you removed metadata from photo object.
Using cascadeInsert allows us not to separately persist photo and separately persist metadata objects now. Now we can simply persist a photo object, and metadata object will persist automatically because of cascade options.
;
Creating a many-to-one / one-to-many relation
Let's create a many-to-one / one-to-many relation. Let's say a photo has one author, and each author can have many photos. First, let's create Author class:
;; @ @ id: number; @ name: string; @ // Note: we will create author property in the Photo class below photos: Photo;
Author contains an inverse side of a relationship. OneToMany is always an inverse side of relation, and it can't exist without ManyToOne of the other side of relationship.
Now let's add owner side of relationship into the Photo entity:
;;; @ /* ... other columns */ @ author: Author;
In many-to-one / one-to-many relation, owner side is always many-to-one.
It means that class which uses @ManyToOne
will store id of the related object.
After you run application ORM will create author table:
+-------------+--------------+----------------------------+| author |+-------------+--------------+----------------------------+| id | int | PRIMARY KEY AUTO_INCREMENT || name | varchar | |+-------------+--------------+----------------------------+
It will also modify photo table - add a new column author and create a foreign key for it:
+-------------+--------------+----------------------------+| photo |+-------------+--------------+----------------------------+| id | int | PRIMARY KEY AUTO_INCREMENT || name | varchar | || description | varchar | || filename | varchar | || isPublished | boolean | || author | int | FOREIGN KEY |+-------------+--------------+----------------------------+
Creating a many-to-many relation
Let's create a many-to-one / many-to-many relation.
Let's say a photo can be in many albums, and multiple can have many photos.
Let's create an Album
class:
; @ @ id: number; @ name: string; @ @ photos: Photo = ; // We initialize array for convinience here
@JoinTable
is required to specify that this is owner side of the relationship.
Now let's add inverse side of our relation to the Photo
class:
/// ... other columns @ albums: Album = ; // We initialize array for convinience here
After you run application ORM will create a album_photos_photo_albums junction table:
+-------------+--------------+----------------------------+| album_photos_photo_albums |+-------------+--------------+----------------------------+| album_id_1 | int | PRIMARY KEY FOREIGN KEY || photo_id_2 | int | PRIMARY KEY FOREIGN KEY |+-------------+--------------+----------------------------+
Don't forget to register Album
class for your connection in the ORM:
const options: CreateConnectionOptions = // ... other options entities: Photo PhotoMetadata Author Album;
Now let's insert albums and photos to our database:
let connection = await ; // Create a few albumslet album1 = ;album1name = "Bears"; let album2 = ;album2name = "Me"; // Create a few photoslet photo1 = ;photo1name = "Me and Bears";photo1description = "I am near polar bears";photo1filename = "photo-with-bears.jpg";photo1albums; let photo2 = ;photo2name = "Me and Bears";photo2description = "I am near polar bears";photo2filename = "photo-with-bears.jpg";photo2albums; // Get entity repositorylet photoRepository = connection; // First save a first photo// We only save the photos, albums are persisted// automatically because of cascade optionsawait photoRepository; // Second save a first photoawait photoRepository; console;
Using QueryBuilder
You can use QueryBuilder to build even more complex queries. For example, you can do this:
let photoRepository = connection;let photos = await photoRepository // first argument is an alias. Alias is what you are selecting - photos. You must specify it. ;
This query builder will select you all photos that are published and whose name is "My" or "Mishka", it will select results from 5 position (pagination offset), and will select only 10 results (pagination limit). Selection result will be ordered by id in descending order. Photo's albums will be left-joined and photo's metadata will be inner joined.
You'll use query builder in your application a lot. Learn more about QueryBuilder here.
Learn more
- Connection and connection options
- Connection Manager
- Databases and drivers
- Updating database schema
- Tables and columns
- Relations
- Indices
- Repository
- Query Builder
- Entity Manager
- Subscribers and entity listeners
- Migrations
- Using service container
- Decorators Reference
- Usage in the browser
- Using with JavaScript
Samples
Take a look on samples in ./sample for examples of usage.
There are few repositories which you can clone and start with:
- Example how to use TypeORM with TypeScript
- Example how to use TypeORM with JavaScript
- Example how to use TypeORM with JavaScript and Babel
- Example how to use TypeORM with TypeScript and SystemJS in Browser
- Example how to use Express and TypeORM with TypeScript
- Example how to use Koa and TypeORM with TypeScript
Extensions
There are several extensions that simplify TypeORM integration with other modules:
Contributing
Learn about contribution here and how to setup your development environment here.