added some relations docs

This commit is contained in:
Umed Khudoiberdiev 2017-07-31 17:35:58 +05:00
parent c5d1b21c90
commit d4cb010875
3 changed files with 187 additions and 96 deletions

View File

@ -426,7 +426,7 @@ createConnection(/*...*/).then(connection => {
photo.isPublished = true;
   return connection.manager
.persist(photo)
.save(photo)
.then(photo => {
console.log("Photo has been saved");
});
@ -451,7 +451,7 @@ createConnection(/*...*/).then(async connection => {
photo.views = 1;
photo.isPublished = true;
await connection.manager.persist(photo);
await connection.manager.save(photo);
console.log("Photo has been saved");
}).catch(error => console.log(error));
@ -501,7 +501,7 @@ createConnection(/*...*/).then(async connection => {
let photoRepository = connection.getRepository(Photo);
await photoRepository.persist(photo);
await photoRepository.save(photo);
console.log("Photo has been saved");
let savedPhotos = await photoRepository.find();
@ -556,7 +556,7 @@ createConnection(/*...*/).then(async connection => {
/*...*/
let photoToUpdate = await photoRepository.findOneById(1);
photoToUpdate.name = "Me, my friends and polar bears";
await photoRepository.persist(photoToUpdate);
await photoRepository.save(photoToUpdate);
}).catch(error => console.log(error));
```
@ -677,10 +677,10 @@ createConnection(/*...*/).then(async connection => {
let metadataRepository = connection.getRepository(PhotoMetadata);
// First we should persist a photo
await photoRepository.persist(photo);
await photoRepository.save(photo);
// Photo is saved. Now we need to persist a photo metadata
await metadataRepository.persist(metadata);
await metadataRepository.save(metadata);
// Done
console.log("Metadata is saved, and relation between metadata and photo is created in the database too");
@ -841,7 +841,7 @@ createConnection(options).then(async connection => {
let photoRepository = connection.getRepository(Photo);
// Persisting a photo also persist the metadata
await photoRepository.persist(photo);
await photoRepository.save(photo);
console.log("Photo is saved, photo metadata is saved too.")
@ -1016,10 +1016,10 @@ let photoRepository = connection.getRepository(Photo);
// First save a first photo
// We only save the photos, albums are persisted
// automatically because of cascade options
await photoRepository.persist(photo1);
await photoRepository.save(photo1);
// Second save a first photo
await photoRepository.persist(photo2);
await photoRepository.save(photo2);
console.log("Both photos have been saved");
```

View File

@ -1,85 +0,0 @@
# Columns
* What is Entity Column?
* Primary columns
* Column types
* Column types for `mysql` / `mariadb`
* Column types for `postgres`
* Column types for `sqlite` / `websql`
* Column types for `mssql`
* Column types for `mongodb`
## What is Entity Column?
Entity is a class that maps into database table (or collection for MongoDB database).
You can create entity by defining a new class and mark with special orm decorator:
```typescript
import {Entity, PrimaryGeneratedColumn, Column} from "typeorm";
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column()
firstName: string;
@Column()
lastName: string;
@Column()
isActive: boolean;
}
```
This will create following database table:
```shell
+-------------+--------------+----------------------------+
| user |
+-------------+--------------+----------------------------+
| id | int(11) | PRIMARY KEY AUTO_INCREMENT |
| firstName | varchar(255) | |
| lastName | varchar(255) | |
| isActive | boolean | |
+-------------+--------------+----------------------------+
```
Basic entity consist of columns and relations.
Each entity **MUST** have a primary column (or ObjectId column if are using MongoDB).
Each entity must be registered in your connection options this way:
```typescript
import {createConnection, Connection} from "typeorm";
import {User} from "./entity/User";
const connection: Connection = await createConnection({
type: "mysql",
host: "localhost",
port: 3306,
username: "test",
password: "test",
database: "test",
entities: [User]
});
```
Or you can specify the whole directory with all entities inside - and all of them will be loaded:
```typescript
import {createConnection, Connection} from "typeorm";
const connection: Connection = await createConnection({
type: "mysql",
host: "localhost",
port: 3306,
username: "test",
password: "test",
database: "test",
entities: ["entity/*.js"]
});
```

View File

@ -2,10 +2,186 @@
* What are relations
* One-to-one relation
* Many-to-one / One-to-many relations
* Many-to-one / one-to-many relations
* Many-to-many relation
* Having both relation and relation column
* How to load relations in entities
* Self referencing
* Relation options
* Lazy relations
* Eager relations
* Usage examples
* Usage examples
## What are relations
Relations helps to work with related entities easily.
There are several types of relations:
* one-to-one using `@OneToOne` decorator
* many-to-one using `@ManyToOne` decorator
* one-to-many using `@OneToMany` decorator
* many-to-many using `@ManyToMany` decorator
## One-to-one relation
Let's create an example of one-to-one relation between `User` and `Profile`.
User can have a single profile and single profile can be one for a single user.
```typescript
import {Entity, PrimaryGeneratedColumn, Column} from "typeorm";
@Entity()
export class Profile {
@PrimaryGeneratedColumn()
id: number;
@Column()
gender: string;
@Column()
photo: string;
}
```
```typescript
import {Entity, PrimaryGeneratedColumn, Column, OneToOne, JoinColumn} from "typeorm";
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@OneToOne(type => Profile)
@JoinColumn()
profile: Profile;
}
```
Here we added `@OneToOne` decorator to the `profile` property and specified target relation type `Profile` to it.
We also added `@JoinColumn` decorator which is required and must be set only on one side of relation.
On which side you set `@JoinColumn` that side's table will contain "relation id" and foreign keys to target entity table.
In our example we had one-side-only relation.
This example will produce following tables:
```shell
+-------------+--------------+----------------------------+
| profile |
+-------------+--------------+----------------------------+
| id | int(11) | PRIMARY KEY AUTO_INCREMENT |
| gender | varchar(255) | |
| photo | varchar(255) | |
+-------------+--------------+----------------------------+
+-------------+--------------+----------------------------+
| user |
+-------------+--------------+----------------------------+
| id | int(11) | PRIMARY KEY AUTO_INCREMENT |
| name | varchar(255) | |
| profileId | int(11) | FOREIGN KEY |
+-------------+--------------+----------------------------+
```
Again, `@JoinColumn` must be set only on one side of relation - which side must have foreign key in the database table.
Example how to save such relation:
```typescript
const profile = new Profile();
profile.gender = "male";
profile.photo = "me.jpg";
await connection.manager.save(profile);
const user = new User();
user.profile = profile;
await connection.manager.save(profile);
```
With cascades enabled you can save this relation with only one `save` call.
To load user with profile inside you must specify relation in `FindOptions`:
```typescript
const userRepository = connection.getRepository(User);
const users = await userRepository.find({ relations: ["profile"] });
```
Or using `QueryBuilder` you can join them:
```typescript
const users = await connection
.getRepository(User)
.createQueryBuilder("user")
.leftJoinAndSelect("user.profile", "profile")
.getMany();
```
With eager loading enabled on a relation you don't have to specify relation or join it - it will be loaded automatically ALWAYS.
Relations can be uni-directional and bi-directional.
Uni-directional are relations with relation decorator only on one side.
Bi-directional are relations with decorators on both sides of a relation.
We just created a uni-directional relation. Let's make it bi-directional:
```typescript
import {Entity, PrimaryGeneratedColumn, Column} from "typeorm";
@Entity()
export class Profile {
@PrimaryGeneratedColumn()
id: number;
@Column()
gender: string;
@Column()
photo: string;
@OneToOne(type => User, user => user.profile) // specify inverse side as a second parameter
user: User;
}
```
```typescript
import {Entity, PrimaryGeneratedColumn, Column, OneToOne, JoinColumn} from "typeorm";
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@OneToOne(type => Profile, profile => profile.user) // specify inverse side as a second parameter
@JoinColumn()
profile: Profile;
}
```
We just made our relation bi-directional. Note, inverse relation does not have a `@JoinColumn` decorator.
As we already told you `@JoinColumn` must be only on one side of the relation - which table will own a foreign key.
Bi-directional relations allow you to join relations from both sides using `QueryBuilder`:
```typescript
const profiles = await connection
.getRepository(Profile)
.createQueryBuilder("profile")
.leftJoinAndSelect("profile.user", "user")
.getMany();
```
## Many-to-one / one-to-many relations