typeorm 0.3.1-dev.d61f857 → 0.3.2-dev.b53a481
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +469 -525
- package/browser/driver/postgres/PostgresDriver.js +1 -1
- package/browser/driver/postgres/PostgresDriver.js.map +1 -1
- package/browser/error/index.d.ts +0 -1
- package/browser/error/index.js +0 -1
- package/browser/error/index.js.map +1 -1
- package/browser/find-options/FindOperatorType.d.ts +1 -1
- package/browser/find-options/FindOperatorType.js.map +1 -1
- package/browser/find-options/operator/ArrayContainedBy.d.ts +6 -0
- package/browser/find-options/operator/ArrayContainedBy.js +10 -0
- package/browser/find-options/operator/ArrayContainedBy.js.map +1 -0
- package/browser/find-options/operator/ArrayContains.d.ts +6 -0
- package/browser/find-options/operator/ArrayContains.js +10 -0
- package/browser/find-options/operator/ArrayContains.js.map +1 -0
- package/browser/find-options/operator/ArrayOverlap.d.ts +6 -0
- package/browser/find-options/operator/ArrayOverlap.js +10 -0
- package/browser/find-options/operator/ArrayOverlap.js.map +1 -0
- package/browser/query-builder/QueryBuilder.js +6 -0
- package/browser/query-builder/QueryBuilder.js.map +1 -1
- package/browser/query-builder/WhereClause.d.ts +1 -1
- package/browser/query-builder/WhereClause.js.map +1 -1
- package/driver/postgres/PostgresDriver.js +1 -1
- package/driver/postgres/PostgresDriver.js.map +1 -1
- package/error/index.d.ts +0 -1
- package/error/index.js +0 -1
- package/error/index.js.map +1 -1
- package/find-options/FindOperatorType.d.ts +1 -1
- package/find-options/FindOperatorType.js.map +1 -1
- package/find-options/operator/ArrayContainedBy.d.ts +6 -0
- package/find-options/operator/ArrayContainedBy.js +14 -0
- package/find-options/operator/ArrayContainedBy.js.map +1 -0
- package/find-options/operator/ArrayContains.d.ts +6 -0
- package/find-options/operator/ArrayContains.js +14 -0
- package/find-options/operator/ArrayContains.js.map +1 -0
- package/find-options/operator/ArrayOverlap.d.ts +6 -0
- package/find-options/operator/ArrayOverlap.js +14 -0
- package/find-options/operator/ArrayOverlap.js.map +1 -0
- package/index.mjs +0 -2
- package/package.json +1 -1
- package/query-builder/QueryBuilder.js +6 -0
- package/query-builder/QueryBuilder.js.map +1 -1
- package/query-builder/WhereClause.d.ts +1 -1
- package/query-builder/WhereClause.js.map +1 -1
- package/browser/error/RepositoryNotFoundError.d.ts +0 -8
- package/browser/error/RepositoryNotFoundError.js +0 -30
- package/browser/error/RepositoryNotFoundError.js.map +0 -1
- package/error/RepositoryNotFoundError.d.ts +0 -8
- package/error/RepositoryNotFoundError.js +0 -34
- package/error/RepositoryNotFoundError.js.map +0 -1
package/README.md
CHANGED
|
@@ -34,133 +34,138 @@ which means you can write high quality, loosely coupled, scalable,
|
|
|
34
34
|
maintainable applications the most productive way.
|
|
35
35
|
|
|
36
36
|
TypeORM is highly influenced by other ORMs, such as [Hibernate](http://hibernate.org/orm/),
|
|
37
|
-
|
|
37
|
+
[Doctrine](http://www.doctrine-project.org/) and [Entity Framework](https://www.asp.net/entity-framework).
|
|
38
38
|
|
|
39
39
|
## Features
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
41
|
+
- Supports both [DataMapper](./docs/active-record-data-mapper.md#what-is-the-data-mapper-pattern) and [ActiveRecord](./docs/active-record-data-mapper.md#what-is-the-active-record-pattern) (your choice).
|
|
42
|
+
- Entities and columns.
|
|
43
|
+
- Database-specific column types.
|
|
44
|
+
- Entity manager.
|
|
45
|
+
- Repositories and custom repositories.
|
|
46
|
+
- Clean object relational model.
|
|
47
|
+
- Associations (relations).
|
|
48
|
+
- Eager and lazy relations.
|
|
49
|
+
- Uni-directional, bi-directional and self-referenced relations.
|
|
50
|
+
- Supports multiple inheritance patterns.
|
|
51
|
+
- Cascades.
|
|
52
|
+
- Indices.
|
|
53
|
+
- Transactions.
|
|
54
|
+
- Migrations and automatic migrations generation.
|
|
55
|
+
- Connection pooling.
|
|
56
|
+
- Replication.
|
|
57
|
+
- Using multiple database instances.
|
|
58
|
+
- Working with multiple databases types.
|
|
59
|
+
- Cross-database and cross-schema queries.
|
|
60
|
+
- Elegant-syntax, flexible and powerful QueryBuilder.
|
|
61
|
+
- Left and inner joins.
|
|
62
|
+
- Proper pagination for queries using joins.
|
|
63
|
+
- Query caching.
|
|
64
|
+
- Streaming raw results.
|
|
65
|
+
- Logging.
|
|
66
|
+
- Listeners and subscribers (hooks).
|
|
67
|
+
- Supports closure table pattern.
|
|
68
|
+
- Schema declaration in models or separate configuration files.
|
|
69
|
+
- Connection configuration in json / xml / yml / env formats.
|
|
70
|
+
- Supports MySQL / MariaDB / Postgres / CockroachDB / SQLite / Microsoft SQL Server / Oracle / SAP Hana / sql.js.
|
|
71
|
+
- Supports MongoDB NoSQL database.
|
|
72
|
+
- Works in NodeJS / Browser / Ionic / Cordova / React Native / NativeScript / Expo / Electron platforms.
|
|
73
|
+
- TypeScript and JavaScript support.
|
|
74
|
+
- ESM and CommonJS support.
|
|
75
|
+
- Produced code is performant, flexible, clean and maintainable.
|
|
76
|
+
- Follows all possible best practices.
|
|
77
|
+
- CLI.
|
|
78
78
|
|
|
79
79
|
And more...
|
|
80
80
|
|
|
81
81
|
With TypeORM your models look like this:
|
|
82
82
|
|
|
83
83
|
```javascript
|
|
84
|
-
import { Entity, PrimaryGeneratedColumn, Column } from "typeorm"
|
|
84
|
+
import { Entity, PrimaryGeneratedColumn, Column } from "typeorm"
|
|
85
85
|
|
|
86
86
|
@Entity()
|
|
87
87
|
export class User {
|
|
88
|
-
|
|
89
88
|
@PrimaryGeneratedColumn()
|
|
90
|
-
id: number
|
|
89
|
+
id: number
|
|
91
90
|
|
|
92
91
|
@Column()
|
|
93
|
-
firstName: string
|
|
92
|
+
firstName: string
|
|
94
93
|
|
|
95
94
|
@Column()
|
|
96
|
-
lastName: string
|
|
95
|
+
lastName: string
|
|
97
96
|
|
|
98
97
|
@Column()
|
|
99
|
-
age: number
|
|
100
|
-
|
|
98
|
+
age: number
|
|
101
99
|
}
|
|
102
100
|
```
|
|
103
101
|
|
|
104
102
|
And your domain logic looks like this:
|
|
105
103
|
|
|
106
104
|
```javascript
|
|
107
|
-
const
|
|
105
|
+
const userRepository = MyDataSource.getRepository(User)
|
|
108
106
|
|
|
109
|
-
const user = new User()
|
|
110
|
-
user.firstName = "Timber"
|
|
111
|
-
user.lastName = "Saw"
|
|
112
|
-
user.age = 25
|
|
113
|
-
await
|
|
107
|
+
const user = new User()
|
|
108
|
+
user.firstName = "Timber"
|
|
109
|
+
user.lastName = "Saw"
|
|
110
|
+
user.age = 25
|
|
111
|
+
await userRepository.save(user)
|
|
114
112
|
|
|
115
|
-
const allUsers = await
|
|
116
|
-
const firstUser = await
|
|
117
|
-
|
|
113
|
+
const allUsers = await userRepository.find()
|
|
114
|
+
const firstUser = await userRepository.findOneBy({
|
|
115
|
+
id: 1,
|
|
116
|
+
}) // find by id
|
|
117
|
+
const timber = await userRepository.findOneBy({
|
|
118
|
+
firstName: "Timber",
|
|
119
|
+
lastName: "Saw",
|
|
120
|
+
}) // find by firstName and lastName
|
|
118
121
|
|
|
119
|
-
await
|
|
122
|
+
await userRepository.remove(timber)
|
|
120
123
|
```
|
|
121
124
|
|
|
122
125
|
Alternatively, if you prefer to use the `ActiveRecord` implementation, you can use it as well:
|
|
123
126
|
|
|
124
127
|
```javascript
|
|
125
|
-
import { Entity, PrimaryGeneratedColumn, Column, BaseEntity } from "typeorm"
|
|
128
|
+
import { Entity, PrimaryGeneratedColumn, Column, BaseEntity } from "typeorm"
|
|
126
129
|
|
|
127
130
|
@Entity()
|
|
128
131
|
export class User extends BaseEntity {
|
|
129
|
-
|
|
130
132
|
@PrimaryGeneratedColumn()
|
|
131
|
-
id: number
|
|
133
|
+
id: number
|
|
132
134
|
|
|
133
135
|
@Column()
|
|
134
|
-
firstName: string
|
|
136
|
+
firstName: string
|
|
135
137
|
|
|
136
138
|
@Column()
|
|
137
|
-
lastName: string
|
|
139
|
+
lastName: string
|
|
138
140
|
|
|
139
141
|
@Column()
|
|
140
|
-
age: number
|
|
141
|
-
|
|
142
|
+
age: number
|
|
142
143
|
}
|
|
143
144
|
```
|
|
144
145
|
|
|
145
146
|
And your domain logic will look this way:
|
|
146
147
|
|
|
147
148
|
```javascript
|
|
148
|
-
const user = new User()
|
|
149
|
-
user.firstName = "Timber"
|
|
150
|
-
user.lastName = "Saw"
|
|
151
|
-
user.age = 25
|
|
152
|
-
await user.save()
|
|
153
|
-
|
|
154
|
-
const allUsers = await User.find()
|
|
155
|
-
const firstUser = await User.
|
|
156
|
-
|
|
149
|
+
const user = new User()
|
|
150
|
+
user.firstName = "Timber"
|
|
151
|
+
user.lastName = "Saw"
|
|
152
|
+
user.age = 25
|
|
153
|
+
await user.save()
|
|
154
|
+
|
|
155
|
+
const allUsers = await User.find()
|
|
156
|
+
const firstUser = await User.findOneBy({
|
|
157
|
+
id: 1,
|
|
158
|
+
})
|
|
159
|
+
const timber = await User.findOneBy({
|
|
160
|
+
firstName: "Timber",
|
|
161
|
+
lastName: "Saw"
|
|
162
|
+
})
|
|
157
163
|
|
|
158
|
-
await timber.remove()
|
|
164
|
+
await timber.remove()
|
|
159
165
|
```
|
|
160
166
|
|
|
161
167
|
## Installation
|
|
162
168
|
|
|
163
|
-
|
|
164
169
|
1. Install the npm package:
|
|
165
170
|
|
|
166
171
|
`npm install typeorm --save`
|
|
@@ -171,7 +176,7 @@ await timber.remove();
|
|
|
171
176
|
|
|
172
177
|
and import it somewhere in the global place of your app (for example in `app.ts`):
|
|
173
178
|
|
|
174
|
-
`import "reflect-metadata"
|
|
179
|
+
`import "reflect-metadata"`
|
|
175
180
|
|
|
176
181
|
3. You may need to install node typings:
|
|
177
182
|
|
|
@@ -179,56 +184,55 @@ await timber.remove();
|
|
|
179
184
|
|
|
180
185
|
4. Install a database driver:
|
|
181
186
|
|
|
182
|
-
|
|
187
|
+
- for **MySQL** or **MariaDB**
|
|
183
188
|
|
|
184
189
|
`npm install mysql --save` (you can install `mysql2` instead as well)
|
|
185
190
|
|
|
186
|
-
|
|
191
|
+
- for **PostgreSQL** or **CockroachDB**
|
|
187
192
|
|
|
188
193
|
`npm install pg --save`
|
|
189
194
|
|
|
190
|
-
|
|
195
|
+
- for **SQLite**
|
|
191
196
|
|
|
192
197
|
`npm install sqlite3 --save`
|
|
193
198
|
|
|
194
|
-
|
|
199
|
+
- for **Microsoft SQL Server**
|
|
195
200
|
|
|
196
201
|
`npm install mssql --save`
|
|
197
202
|
|
|
198
|
-
|
|
203
|
+
- for **sql.js**
|
|
199
204
|
|
|
200
205
|
`npm install sql.js --save`
|
|
201
206
|
|
|
202
|
-
|
|
207
|
+
- for **Oracle**
|
|
203
208
|
|
|
204
209
|
`npm install oracledb --save`
|
|
205
210
|
|
|
206
211
|
To make the Oracle driver work, you need to follow the installation instructions from
|
|
207
212
|
[their](https://github.com/oracle/node-oracledb) site.
|
|
208
213
|
|
|
209
|
-
|
|
214
|
+
- for **SAP Hana**
|
|
210
215
|
|
|
211
216
|
```
|
|
212
217
|
npm i @sap/hana-client
|
|
213
|
-
|
|
218
|
+
npm i hdb-pool
|
|
214
219
|
```
|
|
215
220
|
|
|
216
|
-
|
|
221
|
+
_SAP Hana support made possible by the sponsorship of [Neptune Software](https://www.neptune-software.com/)._
|
|
217
222
|
|
|
218
|
-
|
|
223
|
+
- for **MongoDB** (experimental)
|
|
219
224
|
|
|
220
225
|
`npm install mongodb@^3.6.0 --save`
|
|
221
226
|
|
|
222
|
-
|
|
227
|
+
- for **NativeScript**, **react-native** and **Cordova**
|
|
223
228
|
|
|
224
229
|
Check [documentation of supported platforms](./docs/supported-platforms.md)
|
|
225
230
|
|
|
226
|
-
Install only
|
|
227
|
-
|
|
231
|
+
Install only _one_ of them, depending on which database you use.
|
|
228
232
|
|
|
229
233
|
##### TypeScript configuration
|
|
230
234
|
|
|
231
|
-
Also, make sure you are using TypeScript version **
|
|
235
|
+
Also, make sure you are using TypeScript version **4.5** or higher,
|
|
232
236
|
and you have enabled the following settings in `tsconfig.json`:
|
|
233
237
|
|
|
234
238
|
```json
|
|
@@ -244,16 +248,10 @@ The quickest way to get started with TypeORM is to use its CLI commands to gener
|
|
|
244
248
|
Quick start works only if you are using TypeORM in a NodeJS application.
|
|
245
249
|
If you are using other platforms, proceed to the [step-by-step guide](#step-by-step-guide).
|
|
246
250
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
```
|
|
250
|
-
npm install typeorm -g
|
|
251
|
-
```
|
|
252
|
-
|
|
253
|
-
Then go to the directory where you want to create a new project and run the command:
|
|
251
|
+
To create a new project using CLI, run the follwing command:
|
|
254
252
|
|
|
255
|
-
```
|
|
256
|
-
typeorm init --name MyProject --database
|
|
253
|
+
```shell
|
|
254
|
+
npx typeorm init --name MyProject --database postgres
|
|
257
255
|
```
|
|
258
256
|
|
|
259
257
|
Where `name` is the name of your project and `database` is the database you'll use.
|
|
@@ -264,49 +262,43 @@ This command will generate a new project in the `MyProject` directory with the f
|
|
|
264
262
|
|
|
265
263
|
```
|
|
266
264
|
MyProject
|
|
267
|
-
├── src
|
|
268
|
-
│ ├── entity
|
|
269
|
-
│ │ └── User.ts
|
|
270
|
-
│ ├── migration
|
|
271
|
-
│
|
|
272
|
-
|
|
273
|
-
├──
|
|
274
|
-
├── package.json
|
|
275
|
-
├── README.md
|
|
276
|
-
└── tsconfig.json
|
|
265
|
+
├── src // place of your TypeScript code
|
|
266
|
+
│ ├── entity // place where your entities (database models) are stored
|
|
267
|
+
│ │ └── User.ts // sample entity
|
|
268
|
+
│ ├── migration // place where your migrations are stored
|
|
269
|
+
│ ├── data-source.ts // data source and all connection configuration
|
|
270
|
+
│ └── index.ts // start point of your application
|
|
271
|
+
├── .gitignore // standard gitignore file
|
|
272
|
+
├── package.json // node module dependencies
|
|
273
|
+
├── README.md // simple readme file
|
|
274
|
+
└── tsconfig.json // TypeScript compiler options
|
|
277
275
|
```
|
|
278
276
|
|
|
279
277
|
> You can also run `typeorm init` on an existing node project, but be careful - it may override some files you already have.
|
|
280
278
|
|
|
281
279
|
The next step is to install new project dependencies:
|
|
282
280
|
|
|
283
|
-
```
|
|
281
|
+
```shell
|
|
284
282
|
cd MyProject
|
|
285
283
|
npm install
|
|
286
284
|
```
|
|
287
285
|
|
|
288
|
-
|
|
286
|
+
After you have all dependencies installed, edit the `data-source.ts` file and put your own database connection configuration options in there:
|
|
289
287
|
|
|
290
|
-
```
|
|
291
|
-
{
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
"src/migration/**/*.ts"
|
|
305
|
-
],
|
|
306
|
-
"subscribers": [
|
|
307
|
-
"src/subscriber/**/*.ts"
|
|
308
|
-
]
|
|
309
|
-
}
|
|
288
|
+
```ts
|
|
289
|
+
export const AppDataSource = new DataSource({
|
|
290
|
+
type: "postgres",
|
|
291
|
+
host: "localhost",
|
|
292
|
+
port: 5432,
|
|
293
|
+
username: "test",
|
|
294
|
+
password: "test",
|
|
295
|
+
database: "test",
|
|
296
|
+
synchronize: true,
|
|
297
|
+
logging: true,
|
|
298
|
+
entities: [Post, Category],
|
|
299
|
+
subscribers: [],
|
|
300
|
+
migrations: [],
|
|
301
|
+
})
|
|
310
302
|
```
|
|
311
303
|
|
|
312
304
|
Particularly, most of the time you'll only need to configure
|
|
@@ -314,7 +306,7 @@ Particularly, most of the time you'll only need to configure
|
|
|
314
306
|
|
|
315
307
|
Once you finish with configuration and all node modules are installed, you can run your application:
|
|
316
308
|
|
|
317
|
-
```
|
|
309
|
+
```shell
|
|
318
310
|
npm start
|
|
319
311
|
```
|
|
320
312
|
|
|
@@ -323,13 +315,13 @@ You can continue to work with this project and integrate other modules you need
|
|
|
323
315
|
creating more entities.
|
|
324
316
|
|
|
325
317
|
> You can generate an ESM project by running
|
|
326
|
-
`typeorm init --name MyProject --database postgres --module esm` command.
|
|
318
|
+
> `npx typeorm init --name MyProject --database postgres --module esm` command.
|
|
327
319
|
|
|
328
320
|
> You can generate an even more advanced project with express installed by running
|
|
329
|
-
`typeorm init --name MyProject --database mysql --express` command.
|
|
321
|
+
> `npx typeorm init --name MyProject --database mysql --express` command.
|
|
330
322
|
|
|
331
323
|
> You can generate a docker-compose file by running
|
|
332
|
-
`typeorm init --name MyProject --database postgres --docker` command.
|
|
324
|
+
> `npx typeorm init --name MyProject --database postgres --docker` command.
|
|
333
325
|
|
|
334
326
|
## Step-by-Step Guide
|
|
335
327
|
|
|
@@ -350,46 +342,46 @@ For example, you have a `Photo` model:
|
|
|
350
342
|
|
|
351
343
|
```javascript
|
|
352
344
|
export class Photo {
|
|
353
|
-
id: number
|
|
354
|
-
name: string
|
|
355
|
-
description: string
|
|
356
|
-
filename: string
|
|
357
|
-
views: number
|
|
358
|
-
isPublished: boolean
|
|
345
|
+
id: number
|
|
346
|
+
name: string
|
|
347
|
+
description: string
|
|
348
|
+
filename: string
|
|
349
|
+
views: number
|
|
350
|
+
isPublished: boolean
|
|
359
351
|
}
|
|
360
352
|
```
|
|
361
353
|
|
|
362
354
|
And you want to store photos in your database.
|
|
363
355
|
To store things in the database, first, you need a database table,
|
|
364
356
|
and database tables are created from your models.
|
|
365
|
-
Not all models, but only those you define as
|
|
357
|
+
Not all models, but only those you define as _entities_.
|
|
366
358
|
|
|
367
359
|
### Create an entity
|
|
368
360
|
|
|
369
|
-
|
|
361
|
+
_Entity_ is your model decorated by an `@Entity` decorator.
|
|
370
362
|
A database table will be created for such models.
|
|
371
|
-
You work with entities everywhere
|
|
363
|
+
You work with entities everywhere in TypeORM.
|
|
372
364
|
You can load/insert/update/remove and perform other operations with them.
|
|
373
365
|
|
|
374
|
-
Let's make our `Photo` model
|
|
366
|
+
Let's make our `Photo` model an entity:
|
|
375
367
|
|
|
376
368
|
```javascript
|
|
377
|
-
import { Entity } from "typeorm"
|
|
369
|
+
import { Entity } from "typeorm"
|
|
378
370
|
|
|
379
371
|
@Entity()
|
|
380
372
|
export class Photo {
|
|
381
|
-
id: number
|
|
382
|
-
name: string
|
|
383
|
-
description: string
|
|
384
|
-
filename: string
|
|
385
|
-
views: number
|
|
386
|
-
isPublished: boolean
|
|
373
|
+
id: number
|
|
374
|
+
name: string
|
|
375
|
+
description: string
|
|
376
|
+
filename: string
|
|
377
|
+
views: number
|
|
378
|
+
isPublished: boolean
|
|
387
379
|
}
|
|
388
380
|
```
|
|
389
381
|
|
|
390
382
|
Now, a database table will be created for the `Photo` entity and we'll be able to work with it anywhere in our app.
|
|
391
383
|
We have created a database table, however, what table can exist without columns?
|
|
392
|
-
Let's create
|
|
384
|
+
Let's create few columns in our database table.
|
|
393
385
|
|
|
394
386
|
### Adding table columns
|
|
395
387
|
|
|
@@ -397,28 +389,27 @@ To add database columns, you simply need to decorate an entity's properties you
|
|
|
397
389
|
with a `@Column` decorator.
|
|
398
390
|
|
|
399
391
|
```javascript
|
|
400
|
-
import { Entity, Column } from "typeorm"
|
|
392
|
+
import { Entity, Column } from "typeorm"
|
|
401
393
|
|
|
402
394
|
@Entity()
|
|
403
395
|
export class Photo {
|
|
404
|
-
|
|
405
396
|
@Column()
|
|
406
|
-
id: number
|
|
397
|
+
id: number
|
|
407
398
|
|
|
408
399
|
@Column()
|
|
409
|
-
name: string
|
|
400
|
+
name: string
|
|
410
401
|
|
|
411
402
|
@Column()
|
|
412
|
-
description: string
|
|
403
|
+
description: string
|
|
413
404
|
|
|
414
405
|
@Column()
|
|
415
|
-
filename: string
|
|
406
|
+
filename: string
|
|
416
407
|
|
|
417
408
|
@Column()
|
|
418
|
-
views: number
|
|
409
|
+
views: number
|
|
419
410
|
|
|
420
411
|
@Column()
|
|
421
|
-
isPublished: boolean
|
|
412
|
+
isPublished: boolean
|
|
422
413
|
}
|
|
423
414
|
```
|
|
424
415
|
|
|
@@ -437,28 +428,27 @@ This is a requirement and you can't avoid it.
|
|
|
437
428
|
To make a column a primary key, you need to use the `@PrimaryColumn` decorator.
|
|
438
429
|
|
|
439
430
|
```javascript
|
|
440
|
-
import { Entity, Column, PrimaryColumn } from "typeorm"
|
|
431
|
+
import { Entity, Column, PrimaryColumn } from "typeorm"
|
|
441
432
|
|
|
442
433
|
@Entity()
|
|
443
434
|
export class Photo {
|
|
444
|
-
|
|
445
435
|
@PrimaryColumn()
|
|
446
|
-
id: number
|
|
436
|
+
id: number
|
|
447
437
|
|
|
448
438
|
@Column()
|
|
449
|
-
name: string
|
|
439
|
+
name: string
|
|
450
440
|
|
|
451
441
|
@Column()
|
|
452
|
-
description: string
|
|
442
|
+
description: string
|
|
453
443
|
|
|
454
444
|
@Column()
|
|
455
|
-
filename: string
|
|
445
|
+
filename: string
|
|
456
446
|
|
|
457
447
|
@Column()
|
|
458
|
-
views: number
|
|
448
|
+
views: number
|
|
459
449
|
|
|
460
450
|
@Column()
|
|
461
|
-
isPublished: boolean
|
|
451
|
+
isPublished: boolean
|
|
462
452
|
}
|
|
463
453
|
```
|
|
464
454
|
|
|
@@ -468,28 +458,27 @@ Now, let's say you want your id column to be auto-generated (this is known as au
|
|
|
468
458
|
To do that, you need to change the `@PrimaryColumn` decorator to a `@PrimaryGeneratedColumn` decorator:
|
|
469
459
|
|
|
470
460
|
```javascript
|
|
471
|
-
import { Entity, Column, PrimaryGeneratedColumn } from "typeorm"
|
|
461
|
+
import { Entity, Column, PrimaryGeneratedColumn } from "typeorm"
|
|
472
462
|
|
|
473
463
|
@Entity()
|
|
474
464
|
export class Photo {
|
|
475
|
-
|
|
476
465
|
@PrimaryGeneratedColumn()
|
|
477
|
-
id: number
|
|
466
|
+
id: number
|
|
478
467
|
|
|
479
468
|
@Column()
|
|
480
|
-
name: string
|
|
469
|
+
name: string
|
|
481
470
|
|
|
482
471
|
@Column()
|
|
483
|
-
description: string
|
|
472
|
+
description: string
|
|
484
473
|
|
|
485
474
|
@Column()
|
|
486
|
-
filename: string
|
|
475
|
+
filename: string
|
|
487
476
|
|
|
488
477
|
@Column()
|
|
489
|
-
views: number
|
|
478
|
+
views: number
|
|
490
479
|
|
|
491
480
|
@Column()
|
|
492
|
-
isPublished: boolean
|
|
481
|
+
isPublished: boolean
|
|
493
482
|
}
|
|
494
483
|
```
|
|
495
484
|
|
|
@@ -501,30 +490,29 @@ We don't want all our columns to be limited varchars or integers.
|
|
|
501
490
|
Let's setup correct data types:
|
|
502
491
|
|
|
503
492
|
```javascript
|
|
504
|
-
import { Entity, Column, PrimaryGeneratedColumn } from "typeorm"
|
|
493
|
+
import { Entity, Column, PrimaryGeneratedColumn } from "typeorm"
|
|
505
494
|
|
|
506
495
|
@Entity()
|
|
507
496
|
export class Photo {
|
|
508
|
-
|
|
509
497
|
@PrimaryGeneratedColumn()
|
|
510
|
-
id: number
|
|
498
|
+
id: number
|
|
511
499
|
|
|
512
500
|
@Column({
|
|
513
|
-
length: 100
|
|
501
|
+
length: 100,
|
|
514
502
|
})
|
|
515
|
-
name: string
|
|
503
|
+
name: string
|
|
516
504
|
|
|
517
505
|
@Column("text")
|
|
518
|
-
description: string
|
|
506
|
+
description: string
|
|
519
507
|
|
|
520
508
|
@Column()
|
|
521
|
-
filename: string
|
|
509
|
+
filename: string
|
|
522
510
|
|
|
523
511
|
@Column("double")
|
|
524
|
-
views: number
|
|
512
|
+
views: number
|
|
525
513
|
|
|
526
514
|
@Column()
|
|
527
|
-
isPublished: boolean
|
|
515
|
+
isPublished: boolean
|
|
528
516
|
}
|
|
529
517
|
```
|
|
530
518
|
|
|
@@ -532,79 +520,52 @@ Column types are database-specific.
|
|
|
532
520
|
You can set any column type your database supports.
|
|
533
521
|
More information on supported column types can be found [here](./docs/entities.md#column-types).
|
|
534
522
|
|
|
535
|
-
### Creating a
|
|
523
|
+
### Creating a new `DataSource`
|
|
536
524
|
|
|
537
|
-
Now, when our entity is created, let's create
|
|
525
|
+
Now, when our entity is created, let's create `index.ts` file and set up our `DataSource` there:
|
|
538
526
|
|
|
539
527
|
```javascript
|
|
540
|
-
import "reflect-metadata"
|
|
541
|
-
import {
|
|
542
|
-
import { Photo } from "./entity/Photo"
|
|
528
|
+
import "reflect-metadata"
|
|
529
|
+
import { DataSource } from "typeorm"
|
|
530
|
+
import { Photo } from "./entity/Photo"
|
|
543
531
|
|
|
544
|
-
|
|
545
|
-
type: "
|
|
532
|
+
const AppDataSource = new DataSource({
|
|
533
|
+
type: "postgres",
|
|
546
534
|
host: "localhost",
|
|
547
|
-
port:
|
|
535
|
+
port: 5432,
|
|
548
536
|
username: "root",
|
|
549
537
|
password: "admin",
|
|
550
538
|
database: "test",
|
|
551
|
-
entities: [
|
|
552
|
-
Photo
|
|
553
|
-
],
|
|
539
|
+
entities: [Photo],
|
|
554
540
|
synchronize: true,
|
|
555
|
-
logging: false
|
|
556
|
-
})
|
|
557
|
-
|
|
558
|
-
|
|
541
|
+
logging: false,
|
|
542
|
+
})
|
|
543
|
+
|
|
544
|
+
// to initialize initial connection with the database, register all entities
|
|
545
|
+
// and "synchronize" database schema, call "initialize()" method of a newly created database
|
|
546
|
+
// once in your application bootstrap
|
|
547
|
+
AppDataSource.initialize()
|
|
548
|
+
.then(() => {
|
|
549
|
+
// here you can start to work with your database
|
|
550
|
+
})
|
|
551
|
+
.catch((error) => console.log(error))
|
|
559
552
|
```
|
|
560
553
|
|
|
561
|
-
We are using
|
|
554
|
+
We are using Postgres in this example, but you can use any other supported database.
|
|
562
555
|
To use another database, simply change the `type` in the options to the database type you are using:
|
|
563
556
|
`mysql`, `mariadb`, `postgres`, `cockroachdb`, `sqlite`, `mssql`, `oracle`, `cordova`, `nativescript`, `react-native`,
|
|
564
557
|
`expo`, or `mongodb`.
|
|
565
558
|
Also make sure to use your own host, port, username, password and database settings.
|
|
566
559
|
|
|
567
|
-
We added our Photo entity to the list of entities for this
|
|
560
|
+
We added our Photo entity to the list of entities for this data source.
|
|
568
561
|
Each entity you are using in your connection must be listed there.
|
|
569
562
|
|
|
570
563
|
Setting `synchronize` makes sure your entities will be synced with the database, every time you run the application.
|
|
571
564
|
|
|
572
|
-
### Loading all entities from the directory
|
|
573
|
-
|
|
574
|
-
Later, when we create more entities we need to add them to the entities in our configuration.
|
|
575
|
-
This is not very convenient, so instead, we can set up the whole directory, from where all entities will be connected and used in our connection:
|
|
576
|
-
|
|
577
|
-
```javascript
|
|
578
|
-
import { createConnection } from "typeorm";
|
|
579
|
-
|
|
580
|
-
createConnection({
|
|
581
|
-
type: "mysql",
|
|
582
|
-
host: "localhost",
|
|
583
|
-
port: 3306,
|
|
584
|
-
username: "root",
|
|
585
|
-
password: "admin",
|
|
586
|
-
database: "test",
|
|
587
|
-
entities: [
|
|
588
|
-
__dirname + "/entity/*.js"
|
|
589
|
-
],
|
|
590
|
-
synchronize: true,
|
|
591
|
-
}).then(connection => {
|
|
592
|
-
// here you can start to work with your entities
|
|
593
|
-
}).catch(error => console.log(error));
|
|
594
|
-
```
|
|
595
|
-
|
|
596
|
-
But be careful with this approach.
|
|
597
|
-
If you are using `ts-node` then you need to specify paths to `.ts` files instead.
|
|
598
|
-
If you are using `outDir` then you'll need to specify paths to `.js` files inside the outDir directory.
|
|
599
|
-
If you are using `outDir` and when you remove or rename your entities make sure to clear `outDir` directory
|
|
600
|
-
and re-compile your project again, because when you remove your source `.ts` files their compiled `.js` versions
|
|
601
|
-
aren't removed from output directory and still are loaded by TypeORM because they are present in the `outDir` directory.
|
|
602
|
-
|
|
603
565
|
### Running the application
|
|
604
566
|
|
|
605
567
|
Now if you run your `index.ts`, a connection with the database will be initialized and a database table for your photos will be created.
|
|
606
568
|
|
|
607
|
-
|
|
608
569
|
```shell
|
|
609
570
|
+-------------+--------------+----------------------------+
|
|
610
571
|
| photo |
|
|
@@ -623,54 +584,25 @@ Now if you run your `index.ts`, a connection with the database will be initializ
|
|
|
623
584
|
Now let's create a new photo to save it in the database:
|
|
624
585
|
|
|
625
586
|
```javascript
|
|
626
|
-
import {
|
|
627
|
-
import { Photo } from "./entity/Photo"
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
photo.isPublished = true;
|
|
637
|
-
|
|
638
|
-
return connection.manager
|
|
639
|
-
.save(photo)
|
|
640
|
-
.then(photo => {
|
|
641
|
-
console.log("Photo has been saved. Photo id is", photo.id);
|
|
642
|
-
});
|
|
587
|
+
import { DataSource } from "typeorm"
|
|
588
|
+
import { Photo } from "./entity/Photo"
|
|
589
|
+
import { AppDataSource } from "./index"
|
|
590
|
+
|
|
591
|
+
const photo = new Photo()
|
|
592
|
+
photo.name = "Me and Bears"
|
|
593
|
+
photo.description = "I am near polar bears"
|
|
594
|
+
photo.filename = "photo-with-bears.jpg"
|
|
595
|
+
photo.views = 1
|
|
596
|
+
photo.isPublished = true
|
|
643
597
|
|
|
644
|
-
|
|
598
|
+
await AppDataSource.manager.save(photo)
|
|
599
|
+
console.log("Photo has been saved. Photo id is", photo.id)
|
|
645
600
|
```
|
|
646
601
|
|
|
647
602
|
Once your entity is saved it will get a newly generated id.
|
|
648
603
|
`save` method returns an instance of the same object you pass to it.
|
|
649
604
|
It's not a new copy of the object, it modifies its "id" and returns it.
|
|
650
605
|
|
|
651
|
-
### Using async/await syntax
|
|
652
|
-
|
|
653
|
-
Let's take advantage of the latest ES8 (ES2017) features and use async/await syntax instead:
|
|
654
|
-
|
|
655
|
-
```javascript
|
|
656
|
-
import { createConnection } from "typeorm";
|
|
657
|
-
import { Photo } from "./entity/Photo";
|
|
658
|
-
|
|
659
|
-
createConnection(/*...*/).then(async connection => {
|
|
660
|
-
|
|
661
|
-
let photo = new Photo();
|
|
662
|
-
photo.name = "Me and Bears";
|
|
663
|
-
photo.description = "I am near polar bears";
|
|
664
|
-
photo.filename = "photo-with-bears.jpg";
|
|
665
|
-
photo.views = 1;
|
|
666
|
-
photo.isPublished = true;
|
|
667
|
-
|
|
668
|
-
await connection.manager.save(photo);
|
|
669
|
-
console.log("Photo has been saved");
|
|
670
|
-
|
|
671
|
-
}).catch(error => console.log(error));
|
|
672
|
-
```
|
|
673
|
-
|
|
674
606
|
### Using Entity Manager
|
|
675
607
|
|
|
676
608
|
We just created a new photo and saved it in the database.
|
|
@@ -679,16 +611,12 @@ Using entity manager you can manipulate any entity in your app.
|
|
|
679
611
|
For example, let's load our saved entity:
|
|
680
612
|
|
|
681
613
|
```javascript
|
|
682
|
-
import {
|
|
683
|
-
import { Photo } from "./entity/Photo"
|
|
684
|
-
|
|
685
|
-
createConnection(/*...*/).then(async connection => {
|
|
686
|
-
|
|
687
|
-
/*...*/
|
|
688
|
-
let savedPhotos = await connection.manager.find(Photo);
|
|
689
|
-
console.log("All photos from the db: ", savedPhotos);
|
|
614
|
+
import { DataSource } from "typeorm"
|
|
615
|
+
import { Photo } from "./entity/Photo"
|
|
616
|
+
import { AppDataSource } from "./index"
|
|
690
617
|
|
|
691
|
-
|
|
618
|
+
const savedPhotos = await AppDataSource.manager.find(Photo)
|
|
619
|
+
console.log("All photos from the db: ", savedPhotos)
|
|
692
620
|
```
|
|
693
621
|
|
|
694
622
|
`savedPhotos` will be an array of Photo objects with the data loaded from the database.
|
|
@@ -701,29 +629,25 @@ Now let's refactor our code and use `Repository` instead of `EntityManager`.
|
|
|
701
629
|
Each entity has its own repository which handles all operations with its entity.
|
|
702
630
|
When you deal with entities a lot, Repositories are more convenient to use than EntityManagers:
|
|
703
631
|
|
|
704
|
-
|
|
705
632
|
```javascript
|
|
706
|
-
import {
|
|
707
|
-
import { Photo } from "./entity/Photo"
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
photo.isPublished = true;
|
|
717
|
-
|
|
718
|
-
let photoRepository = connection.getRepository(Photo);
|
|
633
|
+
import { DataSource } from "typeorm"
|
|
634
|
+
import { Photo } from "./entity/Photo"
|
|
635
|
+
import { AppDataSource } from "./index"
|
|
636
|
+
|
|
637
|
+
const photo = new Photo()
|
|
638
|
+
photo.name = "Me and Bears"
|
|
639
|
+
photo.description = "I am near polar bears"
|
|
640
|
+
photo.filename = "photo-with-bears.jpg"
|
|
641
|
+
photo.views = 1
|
|
642
|
+
photo.isPublished = true
|
|
719
643
|
|
|
720
|
-
|
|
721
|
-
console.log("Photo has been saved");
|
|
644
|
+
const photoRepository = AppDataSource.getRepository(Photo)
|
|
722
645
|
|
|
723
|
-
|
|
724
|
-
|
|
646
|
+
await photoRepository.save(photo)
|
|
647
|
+
console.log("Photo has been saved")
|
|
725
648
|
|
|
726
|
-
|
|
649
|
+
const savedPhotos = await photoRepository.find()
|
|
650
|
+
console.log("All photos from the db: ", savedPhotos)
|
|
727
651
|
```
|
|
728
652
|
|
|
729
653
|
Learn more about Repository [here](./docs/working-with-repository.md).
|
|
@@ -733,32 +657,32 @@ Learn more about Repository [here](./docs/working-with-repository.md).
|
|
|
733
657
|
Let's try more load operations using the Repository:
|
|
734
658
|
|
|
735
659
|
```javascript
|
|
736
|
-
import {
|
|
737
|
-
import { Photo } from "./entity/Photo"
|
|
660
|
+
import { DataSource } from "typeorm"
|
|
661
|
+
import { Photo } from "./entity/Photo"
|
|
662
|
+
import { AppDataSource } from "./index"
|
|
738
663
|
|
|
739
|
-
|
|
664
|
+
const allPhotos = await photoRepository.find()
|
|
665
|
+
console.log("All photos from the db: ", allPhotos)
|
|
740
666
|
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
let firstPhoto = await photoRepository.findOne(1);
|
|
746
|
-
console.log("First photo from the db: ", firstPhoto);
|
|
747
|
-
|
|
748
|
-
let meAndBearsPhoto = await photoRepository.findOne({ name: "Me and Bears" });
|
|
749
|
-
console.log("Me and Bears photo from the db: ", meAndBearsPhoto);
|
|
667
|
+
const firstPhoto = await photoRepository.findOneBy({
|
|
668
|
+
id: 1,
|
|
669
|
+
})
|
|
670
|
+
console.log("First photo from the db: ", firstPhoto)
|
|
750
671
|
|
|
751
|
-
|
|
752
|
-
|
|
672
|
+
const meAndBearsPhoto = await photoRepository.findOneBy({
|
|
673
|
+
name: "Me and Bears",
|
|
674
|
+
})
|
|
675
|
+
console.log("Me and Bears photo from the db: ", meAndBearsPhoto)
|
|
753
676
|
|
|
754
|
-
|
|
755
|
-
|
|
677
|
+
const allViewedPhotos = await photoRepository.findBy({ views: 1 })
|
|
678
|
+
console.log("All viewed photos: ", allViewedPhotos)
|
|
756
679
|
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
console.log("Photos count: ", photosCount);
|
|
680
|
+
const allPublishedPhotos = await photoRepository.findBy({ isPublished: true })
|
|
681
|
+
console.log("All published photos: ", allPublishedPhotos)
|
|
760
682
|
|
|
761
|
-
|
|
683
|
+
const [photos, photosCount] = await photoRepository.findAndCount()
|
|
684
|
+
console.log("All photos: ", photos)
|
|
685
|
+
console.log("Photos count: ", photosCount)
|
|
762
686
|
```
|
|
763
687
|
|
|
764
688
|
### Updating in the database
|
|
@@ -766,17 +690,16 @@ createConnection(/*...*/).then(async connection => {
|
|
|
766
690
|
Now let's load a single photo from the database, update it and save it:
|
|
767
691
|
|
|
768
692
|
```javascript
|
|
769
|
-
import {
|
|
770
|
-
import { Photo } from "./entity/Photo"
|
|
771
|
-
|
|
772
|
-
createConnection(/*...*/).then(async connection => {
|
|
773
|
-
|
|
774
|
-
/*...*/
|
|
775
|
-
let photoToUpdate = await photoRepository.findOne(1);
|
|
776
|
-
photoToUpdate.name = "Me, my friends and polar bears";
|
|
777
|
-
await photoRepository.save(photoToUpdate);
|
|
693
|
+
import { DataSource } from "typeorm"
|
|
694
|
+
import { Photo } from "./entity/Photo"
|
|
695
|
+
import { AppDataSource } from "./index"
|
|
778
696
|
|
|
779
|
-
|
|
697
|
+
const photoRepository = AppDataSource.getRepository(Photo)
|
|
698
|
+
const photoToUpdate = await photoRepository.findOneBy({
|
|
699
|
+
id: 1,
|
|
700
|
+
})
|
|
701
|
+
photoToUpdate.name = "Me, my friends and polar bears"
|
|
702
|
+
await photoRepository.save(photoToUpdate)
|
|
780
703
|
```
|
|
781
704
|
|
|
782
705
|
Now photo with `id = 1` will be updated in the database.
|
|
@@ -786,16 +709,15 @@ Now photo with `id = 1` will be updated in the database.
|
|
|
786
709
|
Now let's remove our photo from the database:
|
|
787
710
|
|
|
788
711
|
```javascript
|
|
789
|
-
import {
|
|
790
|
-
import { Photo } from "./entity/Photo"
|
|
791
|
-
|
|
792
|
-
createConnection(/*...*/).then(async connection => {
|
|
793
|
-
|
|
794
|
-
/*...*/
|
|
795
|
-
let photoToRemove = await photoRepository.findOne(1);
|
|
796
|
-
await photoRepository.remove(photoToRemove);
|
|
712
|
+
import { DataSource } from "typeorm"
|
|
713
|
+
import { Photo } from "./entity/Photo"
|
|
714
|
+
import { AppDataSource } from "./index"
|
|
797
715
|
|
|
798
|
-
|
|
716
|
+
const photoRepository = AppDataSource.getRepository(Photo)
|
|
717
|
+
const photoToRemove = await photoRepository.findOneBy({
|
|
718
|
+
id: 1,
|
|
719
|
+
})
|
|
720
|
+
await photoRepository.remove(photoToRemove)
|
|
799
721
|
```
|
|
800
722
|
|
|
801
723
|
Now photo with `id = 1` will be removed from the database.
|
|
@@ -806,33 +728,38 @@ Let's create a one-to-one relationship with another class.
|
|
|
806
728
|
Let's create a new class in `PhotoMetadata.ts`. This PhotoMetadata class is supposed to contain our photo's additional meta-information:
|
|
807
729
|
|
|
808
730
|
```javascript
|
|
809
|
-
import {
|
|
810
|
-
|
|
731
|
+
import {
|
|
732
|
+
Entity,
|
|
733
|
+
Column,
|
|
734
|
+
PrimaryGeneratedColumn,
|
|
735
|
+
OneToOne,
|
|
736
|
+
JoinColumn,
|
|
737
|
+
} from "typeorm"
|
|
738
|
+
import { Photo } from "./Photo"
|
|
811
739
|
|
|
812
740
|
@Entity()
|
|
813
741
|
export class PhotoMetadata {
|
|
814
|
-
|
|
815
742
|
@PrimaryGeneratedColumn()
|
|
816
|
-
id: number
|
|
743
|
+
id: number
|
|
817
744
|
|
|
818
745
|
@Column("int")
|
|
819
|
-
height: number
|
|
746
|
+
height: number
|
|
820
747
|
|
|
821
748
|
@Column("int")
|
|
822
|
-
width: number
|
|
749
|
+
width: number
|
|
823
750
|
|
|
824
751
|
@Column()
|
|
825
|
-
orientation: string
|
|
752
|
+
orientation: string
|
|
826
753
|
|
|
827
754
|
@Column()
|
|
828
|
-
compressed: boolean
|
|
755
|
+
compressed: boolean
|
|
829
756
|
|
|
830
757
|
@Column()
|
|
831
|
-
comment: string
|
|
758
|
+
comment: string
|
|
832
759
|
|
|
833
|
-
@OneToOne(
|
|
760
|
+
@OneToOne(() => Photo)
|
|
834
761
|
@JoinColumn()
|
|
835
|
-
photo: Photo
|
|
762
|
+
photo: Photo
|
|
836
763
|
}
|
|
837
764
|
```
|
|
838
765
|
|
|
@@ -868,43 +795,41 @@ If you run the app, you'll see a newly generated table, and it will contain a co
|
|
|
868
795
|
Now let's save a photo, its metadata and attach them to each other.
|
|
869
796
|
|
|
870
797
|
```javascript
|
|
871
|
-
import {
|
|
872
|
-
import { Photo } from "./entity/Photo"
|
|
873
|
-
import { PhotoMetadata } from "./entity/PhotoMetadata"
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
}).catch(error => console.log(error));
|
|
798
|
+
import { DataSource } from "typeorm"
|
|
799
|
+
import { Photo } from "./entity/Photo"
|
|
800
|
+
import { PhotoMetadata } from "./entity/PhotoMetadata"
|
|
801
|
+
|
|
802
|
+
// create a photo
|
|
803
|
+
const photo = new Photo()
|
|
804
|
+
photo.name = "Me and Bears"
|
|
805
|
+
photo.description = "I am near polar bears"
|
|
806
|
+
photo.filename = "photo-with-bears.jpg"
|
|
807
|
+
photo.views = 1
|
|
808
|
+
photo.isPublished = true
|
|
809
|
+
|
|
810
|
+
// create a photo metadata
|
|
811
|
+
const metadata = new PhotoMetadata()
|
|
812
|
+
metadata.height = 640
|
|
813
|
+
metadata.width = 480
|
|
814
|
+
metadata.compressed = true
|
|
815
|
+
metadata.comment = "cybershoot"
|
|
816
|
+
metadata.orientation = "portrait"
|
|
817
|
+
metadata.photo = photo // this way we connect them
|
|
818
|
+
|
|
819
|
+
// get entity repositories
|
|
820
|
+
const photoRepository = AppDataSource.getRepository(Photo)
|
|
821
|
+
const metadataRepository = AppDataSource.getRepository(PhotoMetadata)
|
|
822
|
+
|
|
823
|
+
// first we should save a photo
|
|
824
|
+
await photoRepository.save(photo)
|
|
825
|
+
|
|
826
|
+
// photo is saved. Now we need to save a photo metadata
|
|
827
|
+
await metadataRepository.save(metadata)
|
|
828
|
+
|
|
829
|
+
// done
|
|
830
|
+
console.log(
|
|
831
|
+
"Metadata is saved, and the relation between metadata and photo is created in the database too",
|
|
832
|
+
)
|
|
908
833
|
```
|
|
909
834
|
|
|
910
835
|
### Inverse side of the relationship
|
|
@@ -917,31 +842,35 @@ To fix this issue we should add an inverse relation, and make relations between
|
|
|
917
842
|
Let's modify our entities:
|
|
918
843
|
|
|
919
844
|
```javascript
|
|
920
|
-
import {
|
|
921
|
-
|
|
845
|
+
import {
|
|
846
|
+
Entity,
|
|
847
|
+
Column,
|
|
848
|
+
PrimaryGeneratedColumn,
|
|
849
|
+
OneToOne,
|
|
850
|
+
JoinColumn,
|
|
851
|
+
} from "typeorm"
|
|
852
|
+
import { Photo } from "./Photo"
|
|
922
853
|
|
|
923
854
|
@Entity()
|
|
924
855
|
export class PhotoMetadata {
|
|
925
|
-
|
|
926
856
|
/* ... other columns */
|
|
927
857
|
|
|
928
|
-
@OneToOne(
|
|
858
|
+
@OneToOne(() => Photo, (photo) => photo.metadata)
|
|
929
859
|
@JoinColumn()
|
|
930
|
-
photo: Photo
|
|
860
|
+
photo: Photo
|
|
931
861
|
}
|
|
932
862
|
```
|
|
933
863
|
|
|
934
864
|
```javascript
|
|
935
|
-
import { Entity, Column, PrimaryGeneratedColumn, OneToOne } from "typeorm"
|
|
936
|
-
import { PhotoMetadata } from "./PhotoMetadata"
|
|
865
|
+
import { Entity, Column, PrimaryGeneratedColumn, OneToOne } from "typeorm"
|
|
866
|
+
import { PhotoMetadata } from "./PhotoMetadata"
|
|
937
867
|
|
|
938
868
|
@Entity()
|
|
939
869
|
export class Photo {
|
|
940
|
-
|
|
941
870
|
/* ... other columns */
|
|
942
871
|
|
|
943
|
-
@OneToOne(
|
|
944
|
-
metadata: PhotoMetadata
|
|
872
|
+
@OneToOne(() => PhotoMetadata, (photoMetadata) => photoMetadata.photo)
|
|
873
|
+
metadata: PhotoMetadata
|
|
945
874
|
}
|
|
946
875
|
```
|
|
947
876
|
|
|
@@ -960,31 +889,42 @@ If you use ESM in your TypeScript project, you should use the `Relation` wrapper
|
|
|
960
889
|
Let's modify our entities:
|
|
961
890
|
|
|
962
891
|
```javascript
|
|
963
|
-
import {
|
|
964
|
-
|
|
892
|
+
import {
|
|
893
|
+
Entity,
|
|
894
|
+
Column,
|
|
895
|
+
PrimaryGeneratedColumn,
|
|
896
|
+
OneToOne,
|
|
897
|
+
JoinColumn,
|
|
898
|
+
Relation,
|
|
899
|
+
} from "typeorm"
|
|
900
|
+
import { Photo } from "./Photo"
|
|
965
901
|
|
|
966
902
|
@Entity()
|
|
967
903
|
export class PhotoMetadata {
|
|
968
|
-
|
|
969
904
|
/* ... other columns */
|
|
970
905
|
|
|
971
|
-
@OneToOne(
|
|
906
|
+
@OneToOne(() => Photo, (photo) => photo.metadata)
|
|
972
907
|
@JoinColumn()
|
|
973
|
-
photo: Relation<Photo
|
|
908
|
+
photo: Relation<Photo>
|
|
974
909
|
}
|
|
975
910
|
```
|
|
976
911
|
|
|
977
912
|
```javascript
|
|
978
|
-
import {
|
|
979
|
-
|
|
913
|
+
import {
|
|
914
|
+
Entity,
|
|
915
|
+
Column,
|
|
916
|
+
PrimaryGeneratedColumn,
|
|
917
|
+
OneToOne,
|
|
918
|
+
Relation,
|
|
919
|
+
} from "typeorm"
|
|
920
|
+
import { PhotoMetadata } from "./PhotoMetadata"
|
|
980
921
|
|
|
981
922
|
@Entity()
|
|
982
923
|
export class Photo {
|
|
983
|
-
|
|
984
924
|
/* ... other columns */
|
|
985
925
|
|
|
986
|
-
@OneToOne(
|
|
987
|
-
metadata: Relation<PhotoMetadata
|
|
926
|
+
@OneToOne(() => PhotoMetadata, (photoMetadata) => photoMetadata.photo)
|
|
927
|
+
metadata: Relation<PhotoMetadata>
|
|
988
928
|
}
|
|
989
929
|
```
|
|
990
930
|
|
|
@@ -996,17 +936,17 @@ Let's use `find*` methods first.
|
|
|
996
936
|
`find*` methods allow you to specify an object with the `FindOneOptions` / `FindManyOptions` interface.
|
|
997
937
|
|
|
998
938
|
```javascript
|
|
999
|
-
import {
|
|
1000
|
-
import { Photo } from "./entity/Photo"
|
|
1001
|
-
import { PhotoMetadata } from "./entity/PhotoMetadata"
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
})
|
|
939
|
+
import { DataSource } from "typeorm"
|
|
940
|
+
import { Photo } from "./entity/Photo"
|
|
941
|
+
import { PhotoMetadata } from "./entity/PhotoMetadata"
|
|
942
|
+
import { AppDataSource } from "./index"
|
|
943
|
+
|
|
944
|
+
const photoRepository = AppDataSource.getRepository(Photo)
|
|
945
|
+
const photos = await photoRepository.find({
|
|
946
|
+
relations: {
|
|
947
|
+
metadata: true,
|
|
948
|
+
},
|
|
949
|
+
})
|
|
1010
950
|
```
|
|
1011
951
|
|
|
1012
952
|
Here, photos will contain an array of photos from the database, and each photo will contain its photo metadata.
|
|
@@ -1016,21 +956,15 @@ Using find options is good and dead simple, but if you need a more complex query
|
|
|
1016
956
|
`QueryBuilder` allows more complex queries to be used in an elegant way:
|
|
1017
957
|
|
|
1018
958
|
```javascript
|
|
1019
|
-
import {
|
|
1020
|
-
import { Photo } from "./entity/Photo"
|
|
1021
|
-
import { PhotoMetadata } from "./entity/PhotoMetadata"
|
|
959
|
+
import { DataSource } from "typeorm"
|
|
960
|
+
import { Photo } from "./entity/Photo"
|
|
961
|
+
import { PhotoMetadata } from "./entity/PhotoMetadata"
|
|
962
|
+
import { AppDataSource } from "./index"
|
|
1022
963
|
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
.getRepository(Photo)
|
|
1028
|
-
.createQueryBuilder("photo")
|
|
1029
|
-
.innerJoinAndSelect("photo.metadata", "metadata")
|
|
1030
|
-
.getMany();
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
}).catch(error => console.log(error));
|
|
964
|
+
const photos = await AppDataSource.getRepository(Photo)
|
|
965
|
+
.createQueryBuilder("photo")
|
|
966
|
+
.innerJoinAndSelect("photo.metadata", "metadata")
|
|
967
|
+
.getMany()
|
|
1034
968
|
```
|
|
1035
969
|
|
|
1036
970
|
`QueryBuilder` allows the creation and execution of SQL queries of almost any complexity.
|
|
@@ -1047,10 +981,10 @@ Let's change our photo's `@OneToOne` decorator a bit:
|
|
|
1047
981
|
export class Photo {
|
|
1048
982
|
/// ... other columns
|
|
1049
983
|
|
|
1050
|
-
@OneToOne(
|
|
984
|
+
@OneToOne(() => PhotoMetadata, (metadata) => metadata.photo, {
|
|
1051
985
|
cascade: true,
|
|
1052
986
|
})
|
|
1053
|
-
metadata: PhotoMetadata
|
|
987
|
+
metadata: PhotoMetadata
|
|
1054
988
|
}
|
|
1055
989
|
```
|
|
1056
990
|
|
|
@@ -1058,34 +992,32 @@ Using `cascade` allows us not to separately save photo and separately save metad
|
|
|
1058
992
|
Now we can simply save a photo object, and the metadata object will be saved automatically because of cascade options.
|
|
1059
993
|
|
|
1060
994
|
```javascript
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
// create photo object
|
|
1064
|
-
let photo = new Photo();
|
|
1065
|
-
photo.name = "Me and Bears";
|
|
1066
|
-
photo.description = "I am near polar bears";
|
|
1067
|
-
photo.filename = "photo-with-bears.jpg";
|
|
1068
|
-
photo.isPublished = true;
|
|
995
|
+
import { AppDataSource } from "./index"
|
|
1069
996
|
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
metadata.orientation = "portrait";
|
|
997
|
+
// create photo object
|
|
998
|
+
const photo = new Photo()
|
|
999
|
+
photo.name = "Me and Bears"
|
|
1000
|
+
photo.description = "I am near polar bears"
|
|
1001
|
+
photo.filename = "photo-with-bears.jpg"
|
|
1002
|
+
photo.isPublished = true
|
|
1077
1003
|
|
|
1078
|
-
|
|
1004
|
+
// create photo metadata object
|
|
1005
|
+
const metadata = new PhotoMetadata()
|
|
1006
|
+
metadata.height = 640
|
|
1007
|
+
metadata.width = 480
|
|
1008
|
+
metadata.compressed = true
|
|
1009
|
+
metadata.comment = "cybershoot"
|
|
1010
|
+
metadata.orientation = "portrait"
|
|
1079
1011
|
|
|
1080
|
-
|
|
1081
|
-
let photoRepository = connection.getRepository(Photo);
|
|
1012
|
+
photo.metadata = metadata // this way we connect them
|
|
1082
1013
|
|
|
1083
|
-
|
|
1084
|
-
|
|
1014
|
+
// get repository
|
|
1015
|
+
const photoRepository = AppDataSource.getRepository(Photo)
|
|
1085
1016
|
|
|
1086
|
-
|
|
1017
|
+
// saving a photo also save the metadata
|
|
1018
|
+
await photoRepository.save(photo)
|
|
1087
1019
|
|
|
1088
|
-
|
|
1020
|
+
console.log("Photo is saved, photo metadata is saved too.")
|
|
1089
1021
|
```
|
|
1090
1022
|
|
|
1091
1023
|
Notice that we now set the photo's `metadata` property, instead of the metadata's `photo` property as before. The `cascade` feature only works if you connect the photo to its metadata from the photo's side. If you set the metadata's side, the metadata would not be saved automatically.
|
|
@@ -1097,20 +1029,25 @@ Let's say a photo has one author, and each author can have many photos.
|
|
|
1097
1029
|
First, let's create an `Author` class:
|
|
1098
1030
|
|
|
1099
1031
|
```javascript
|
|
1100
|
-
import {
|
|
1101
|
-
|
|
1032
|
+
import {
|
|
1033
|
+
Entity,
|
|
1034
|
+
Column,
|
|
1035
|
+
PrimaryGeneratedColumn,
|
|
1036
|
+
OneToMany,
|
|
1037
|
+
JoinColumn,
|
|
1038
|
+
} from "typeorm"
|
|
1039
|
+
import { Photo } from "./Photo"
|
|
1102
1040
|
|
|
1103
1041
|
@Entity()
|
|
1104
1042
|
export class Author {
|
|
1105
|
-
|
|
1106
1043
|
@PrimaryGeneratedColumn()
|
|
1107
|
-
id: number
|
|
1044
|
+
id: number
|
|
1108
1045
|
|
|
1109
1046
|
@Column()
|
|
1110
|
-
name: string
|
|
1047
|
+
name: string
|
|
1111
1048
|
|
|
1112
|
-
@OneToMany(
|
|
1113
|
-
photos: Photo[]
|
|
1049
|
+
@OneToMany(() => Photo, (photo) => photo.author) // note: we will create author property in the Photo class below
|
|
1050
|
+
photos: Photo[]
|
|
1114
1051
|
}
|
|
1115
1052
|
```
|
|
1116
1053
|
|
|
@@ -1120,17 +1057,16 @@ export class Author {
|
|
|
1120
1057
|
Now let's add the owner side of the relation into the Photo entity:
|
|
1121
1058
|
|
|
1122
1059
|
```javascript
|
|
1123
|
-
import { Entity, Column, PrimaryGeneratedColumn, ManyToOne } from "typeorm"
|
|
1124
|
-
import { PhotoMetadata } from "./PhotoMetadata"
|
|
1125
|
-
import { Author } from "./Author"
|
|
1060
|
+
import { Entity, Column, PrimaryGeneratedColumn, ManyToOne } from "typeorm"
|
|
1061
|
+
import { PhotoMetadata } from "./PhotoMetadata"
|
|
1062
|
+
import { Author } from "./Author"
|
|
1126
1063
|
|
|
1127
1064
|
@Entity()
|
|
1128
1065
|
export class Photo {
|
|
1129
|
-
|
|
1130
1066
|
/* ... other columns */
|
|
1131
1067
|
|
|
1132
|
-
@ManyToOne(
|
|
1133
|
-
author: Author
|
|
1068
|
+
@ManyToOne(() => Author, (author) => author.photos)
|
|
1069
|
+
author: Author
|
|
1134
1070
|
}
|
|
1135
1071
|
```
|
|
1136
1072
|
|
|
@@ -1139,7 +1075,6 @@ It means that the class that uses `@ManyToOne` will store the id of the related
|
|
|
1139
1075
|
|
|
1140
1076
|
After you run the application, the ORM will create the `author` table:
|
|
1141
1077
|
|
|
1142
|
-
|
|
1143
1078
|
```shell
|
|
1144
1079
|
+-------------+--------------+----------------------------+
|
|
1145
1080
|
| author |
|
|
@@ -1171,20 +1106,25 @@ Let's say a photo can be in many albums, and each album can contain many photos.
|
|
|
1171
1106
|
Let's create an `Album` class:
|
|
1172
1107
|
|
|
1173
1108
|
```javascript
|
|
1174
|
-
import {
|
|
1109
|
+
import {
|
|
1110
|
+
Entity,
|
|
1111
|
+
PrimaryGeneratedColumn,
|
|
1112
|
+
Column,
|
|
1113
|
+
ManyToMany,
|
|
1114
|
+
JoinTable,
|
|
1115
|
+
} from "typeorm"
|
|
1175
1116
|
|
|
1176
1117
|
@Entity()
|
|
1177
1118
|
export class Album {
|
|
1178
|
-
|
|
1179
1119
|
@PrimaryGeneratedColumn()
|
|
1180
|
-
id: number
|
|
1120
|
+
id: number
|
|
1181
1121
|
|
|
1182
1122
|
@Column()
|
|
1183
|
-
name: string
|
|
1123
|
+
name: string
|
|
1184
1124
|
|
|
1185
|
-
@ManyToMany(
|
|
1125
|
+
@ManyToMany(() => Photo, (photo) => photo.albums)
|
|
1186
1126
|
@JoinTable()
|
|
1187
|
-
photos: Photo[]
|
|
1127
|
+
photos: Photo[]
|
|
1188
1128
|
}
|
|
1189
1129
|
```
|
|
1190
1130
|
|
|
@@ -1196,12 +1136,12 @@ Now let's add the inverse side of our relation to the `Photo` class:
|
|
|
1196
1136
|
export class Photo {
|
|
1197
1137
|
/// ... other columns
|
|
1198
1138
|
|
|
1199
|
-
@ManyToMany(
|
|
1200
|
-
albums: Album[]
|
|
1139
|
+
@ManyToMany(() => Album, (album) => album.photos)
|
|
1140
|
+
albums: Album[]
|
|
1201
1141
|
}
|
|
1202
1142
|
```
|
|
1203
1143
|
|
|
1204
|
-
After you run the application, the ORM will create a **album_photos_photo_albums**
|
|
1144
|
+
After you run the application, the ORM will create a **album_photos_photo_albums** _junction table_:
|
|
1205
1145
|
|
|
1206
1146
|
```shell
|
|
1207
1147
|
+-------------+--------------+----------------------------+
|
|
@@ -1215,41 +1155,46 @@ After you run the application, the ORM will create a **album_photos_photo_albums
|
|
|
1215
1155
|
Don't forget to register the `Album` class with your connection in the ORM:
|
|
1216
1156
|
|
|
1217
1157
|
```javascript
|
|
1218
|
-
const options:
|
|
1158
|
+
const options: DataSourceOptions = {
|
|
1219
1159
|
// ... other options
|
|
1220
|
-
entities: [Photo, PhotoMetadata, Author, Album]
|
|
1221
|
-
}
|
|
1160
|
+
entities: [Photo, PhotoMetadata, Author, Album],
|
|
1161
|
+
}
|
|
1222
1162
|
```
|
|
1223
1163
|
|
|
1224
1164
|
Now let's insert albums and photos to our database:
|
|
1225
1165
|
|
|
1226
1166
|
```javascript
|
|
1227
|
-
|
|
1167
|
+
import { AppDataSource } from "./index"
|
|
1228
1168
|
|
|
1229
1169
|
// create a few albums
|
|
1230
|
-
|
|
1231
|
-
album1.name = "Bears"
|
|
1232
|
-
await
|
|
1170
|
+
const album1 = new Album()
|
|
1171
|
+
album1.name = "Bears"
|
|
1172
|
+
await AppDataSource.manager.save(album1)
|
|
1233
1173
|
|
|
1234
|
-
|
|
1235
|
-
album2.name = "Me"
|
|
1236
|
-
await
|
|
1174
|
+
const album2 = new Album()
|
|
1175
|
+
album2.name = "Me"
|
|
1176
|
+
await AppDataSource.manager.save(album2)
|
|
1237
1177
|
|
|
1238
1178
|
// create a few photos
|
|
1239
|
-
|
|
1240
|
-
photo.name = "Me and Bears"
|
|
1241
|
-
photo.description = "I am near polar bears"
|
|
1242
|
-
photo.filename = "photo-with-bears.jpg"
|
|
1179
|
+
const photo = new Photo()
|
|
1180
|
+
photo.name = "Me and Bears"
|
|
1181
|
+
photo.description = "I am near polar bears"
|
|
1182
|
+
photo.filename = "photo-with-bears.jpg"
|
|
1243
1183
|
photo.views = 1
|
|
1244
1184
|
photo.isPublished = true
|
|
1245
|
-
photo.albums = [album1, album2]
|
|
1246
|
-
await
|
|
1185
|
+
photo.albums = [album1, album2]
|
|
1186
|
+
await AppDataSource.manager.save(photo)
|
|
1247
1187
|
|
|
1248
1188
|
// now our photo is saved and albums are attached to it
|
|
1249
1189
|
// now lets load them:
|
|
1250
|
-
const loadedPhoto = await
|
|
1251
|
-
|
|
1252
|
-
|
|
1190
|
+
const loadedPhoto = await AppDataSource.getRepository(Photo).findOne({
|
|
1191
|
+
where: {
|
|
1192
|
+
id: 1,
|
|
1193
|
+
},
|
|
1194
|
+
relations: {
|
|
1195
|
+
albums: true,
|
|
1196
|
+
},
|
|
1197
|
+
})
|
|
1253
1198
|
```
|
|
1254
1199
|
|
|
1255
1200
|
`loadedPhoto` will be equal to:
|
|
@@ -1275,8 +1220,7 @@ const loadedPhoto = await connection
|
|
|
1275
1220
|
You can use QueryBuilder to build SQL queries of almost any complexity. For example, you can do this:
|
|
1276
1221
|
|
|
1277
1222
|
```javascript
|
|
1278
|
-
|
|
1279
|
-
.getRepository(Photo)
|
|
1223
|
+
const photos = await AppDataSource.getRepository(Photo)
|
|
1280
1224
|
.createQueryBuilder("photo") // first argument is an alias. Alias is what you are selecting - photos. You must specify it.
|
|
1281
1225
|
.innerJoinAndSelect("photo.metadata", "metadata")
|
|
1282
1226
|
.leftJoinAndSelect("photo.albums", "album")
|
|
@@ -1286,7 +1230,7 @@ let photos = await connection
|
|
|
1286
1230
|
.skip(5)
|
|
1287
1231
|
.take(10)
|
|
1288
1232
|
.setParameters({ photoName: "My", bearName: "Mishka" })
|
|
1289
|
-
.getMany()
|
|
1233
|
+
.getMany()
|
|
1290
1234
|
```
|
|
1291
1235
|
|
|
1292
1236
|
This query selects all published photos with "My" or "Mishka" names.
|
|
@@ -1304,33 +1248,33 @@ Take a look at the samples in [sample](https://github.com/typeorm/typeorm/tree/m
|
|
|
1304
1248
|
|
|
1305
1249
|
There are a few repositories which you can clone and start with:
|
|
1306
1250
|
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1251
|
+
- [Example how to use TypeORM with TypeScript](https://github.com/typeorm/typescript-example)
|
|
1252
|
+
- [Example how to use TypeORM with JavaScript](https://github.com/typeorm/javascript-example)
|
|
1253
|
+
- [Example how to use TypeORM with JavaScript and Babel](https://github.com/typeorm/babel-example)
|
|
1254
|
+
- [Example how to use TypeORM with TypeScript and SystemJS in Browser](https://github.com/typeorm/browser-example)
|
|
1255
|
+
- [Example how to use TypeORM with TypeScript and React in Browser](https://github.com/ItayGarin/typeorm-react-swc)
|
|
1256
|
+
- [Example how to use Express and TypeORM](https://github.com/typeorm/typescript-express-example)
|
|
1257
|
+
- [Example how to use Koa and TypeORM](https://github.com/typeorm/typescript-koa-example)
|
|
1258
|
+
- [Example how to use TypeORM with MongoDB](https://github.com/typeorm/mongo-typescript-example)
|
|
1259
|
+
- [Example how to use TypeORM in a Cordova/PhoneGap app](https://github.com/typeorm/cordova-example)
|
|
1260
|
+
- [Example how to use TypeORM with an Ionic app](https://github.com/typeorm/ionic-example)
|
|
1261
|
+
- [Example how to use TypeORM with React Native](https://github.com/typeorm/react-native-example)
|
|
1262
|
+
- [Example how to use TypeORM with Nativescript-Vue](https://github.com/typeorm/nativescript-vue-typeorm-sample)
|
|
1263
|
+
- [Example how to use TypeORM with Nativescript-Angular](https://github.com/betov18x/nativescript-angular-typeorm-example)
|
|
1264
|
+
- [Example how to use TypeORM with Electron using JavaScript](https://github.com/typeorm/electron-javascript-example)
|
|
1265
|
+
- [Example how to use TypeORM with Electron using TypeScript](https://github.com/typeorm/electron-typescript-example)
|
|
1322
1266
|
|
|
1323
1267
|
## Extensions
|
|
1324
1268
|
|
|
1325
1269
|
There are several extensions that simplify working with TypeORM and integrating it with other modules:
|
|
1326
1270
|
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1271
|
+
- [TypeORM + GraphQL framework](http://vesper-framework.com)
|
|
1272
|
+
- [TypeORM integration](https://github.com/typeorm/typeorm-typedi-extensions) with [TypeDI](https://github.com/pleerock/typedi)
|
|
1273
|
+
- [TypeORM integration](https://github.com/typeorm/typeorm-routing-controllers-extensions) with [routing-controllers](https://github.com/pleerock/routing-controllers)
|
|
1274
|
+
- Models generation from existing database - [typeorm-model-generator](https://github.com/Kononnable/typeorm-model-generator)
|
|
1275
|
+
- Fixtures loader - [typeorm-fixtures-cli](https://github.com/RobinCK/typeorm-fixtures)
|
|
1276
|
+
- ER Diagram generator - [typeorm-uml](https://github.com/eugene-manuilov/typeorm-uml/)
|
|
1277
|
+
- Create/Drop database - [typeorm-extension](https://github.com/Tada5hi/typeorm-extension)
|
|
1334
1278
|
|
|
1335
1279
|
## Contributing
|
|
1336
1280
|
|