---
title: 'TypeORM'
metaTitle: 'Prisma ORM vs TypeORM'
metaDescription: 'Learn how Prisma compares to TypeORM.'
community_section: true
---

This page compares Prisma ORM and [TypeORM](https://typeorm.io/). If you want to learn how to migrate from TypeORM to Prisma ORM, check out this [guide](/guides/migrate-from-typeorm).

## TypeORM vs Prisma ORM

While Prisma ORM and TypeORM solve similar problems, they work in very different ways.

**TypeORM** is a traditional ORM which maps _tables_ to _model classes_. These model classes can be used to generate SQL migrations. Instances of the model classes then provide an interface for CRUD queries to an application at runtime.

**Prisma ORM** is a new kind of ORM that mitigates many problems of traditional ORMs, such as bloated model instances, mixing business with storage logic, lack of type-safety or unpredictable queries caused e.g. by lazy loading.

It uses the [Prisma schema](/orm/prisma-schema) to define application models in a declarative way. Prisma Migrate then allows to generate SQL migrations from the Prisma schema and executes them against the database. CRUD queries are provided by Prisma Client, a lightweight and entirely type-safe database client for Node.js and TypeScript.

## API design & Level of abstraction

TypeORM and Prisma ORM operate on different levels of abstraction. TypeORM is closer to mirroring SQL in its API while Prisma Client provides a higher-level abstraction that was carefully designed with the common tasks of application developers in mind. Prisma ORM's API design heavily leans on the idea of [making the right thing easy](https://jason.energy/right-thing-easy-thing/).

While Prisma Client operates at a higher level of abstraction, it strives to expose the full power of the underlying database, allowing you to drop down to [raw SQL](/orm/prisma-client/using-raw-sql/raw-queries) at any time if your use case requires it.

The following sections examine a few examples for how Prisma ORM's and TypeORM's APIs differ in certain scenarios and what the rationale of Prisma ORM's API design is in these cases.

### Filtering

TypeORM primarily leans on SQL operators for filtering lists or records, e.g. with the `find` method. Prisma ORM on the other hand, provides a more [generic set of operators](/orm/prisma-client/queries/filtering-and-sorting#filter-conditions-and-operators) that are intuitive to use. It should also be noted that, as explained in the type-safety section [below](#filtering-1), TypeORM loses type-safety in filter queries in many scenarios.

A good example of how the filtering APIs of both TypeORM and Prisma ORM differ is by looking at `string` filters. While TypeORM primarily provides the filter based on the `ILike` operator which comes directly from SQL, Prisma ORM provides more specific operators that developers can use, e.g.: `contains`, `startsWith` and `endsWith`.

<ParallelBlocks>

<block content="Prisma ORM">

```ts
const posts = await prisma.post.findMany({
  where: {
    title: 'Hello World',
  },
})
```

</block>

<block content="TypeORM">

```ts
const posts = await postRepository.find({
  where: {
    title: ILike('Hello World'),
  },
})
```

</block>

</ParallelBlocks>

<ParallelBlocks>

<block content="Prisma ORM">

```ts
const posts = await prisma.post.findMany({
  where: {
    title: { contains: 'Hello World' },
  },
})
```

</block>

<block content="TypeORM">

```ts
const posts = await postRepository.find({
  where: {
    title: ILike('%Hello World%'),
  },
})
```

</block>

</ParallelBlocks>

<ParallelBlocks>

<block content="Prisma ORM">

```ts
const posts = await prisma.post.findMany({
  where: {
    title: { startsWith: 'Hello World' },
  },
})
```

</block>

<block content="TypeORM">

```ts
const posts = await postRepository.find({
  where: {
    title: ILike('Hello World%'),
  },
})
```

</block>

</ParallelBlocks>

<ParallelBlocks>

<block content="Prisma ORM">

```ts
const posts = await prisma.post.findMany({
  where: {
    title: { endsWith: 'Hello World' },
  },
})
```

</block>

<block content="TypeORM">

```ts
const posts = await postRepository.find({
  where: {
    title: ILike('%Hello World'),
  },
})
```

</block>

</ParallelBlocks>

### Pagination

TypeORM only offers limit-offset pagination while Prisma ORM conveniently provides dedicated APIs for both limit-offset but also cursor-based. You can learn more about both approaches in the [Pagination](/orm/prisma-client/queries/pagination) section of the docs or in the API comparison [below](#pagination-1).

### Relations

Working with records that are connected via foreign keys can become very complex in SQL. Prisma ORM's concept of [virtual relation field](/orm/prisma-schema/data-model/relations#relation-fields) enables an intuitive and convenient way for application developers to work with related data. Some benefits of Prisma ORM's approach are:

- traversing relationships via the fluent API ([docs](/orm/prisma-client/queries/relation-queries#fluent-api))
- nested writes that enable updating/creating connected records ([docs](/orm/prisma-client/queries/relation-queries#nested-writes))
- applying filters on related records ([docs](/orm/prisma-client/queries/relation-queries#relation-filters))
- easy and type-safe querying of nested data without worrying about JOINs ([docs](/orm/prisma-client/queries/relation-queries#nested-reads))
- creating nested TypeScript typings based on models and their relations ([docs](/orm/prisma-client/type-safety))
- intuitive modeling of relations in the data model via relation fields ([docs](/orm/prisma-schema/data-model/relations))
- implicit handling of relation tables (also sometimes called JOIN, link, pivot or junction tables) ([docs](/orm/prisma-schema/data-model/relations/many-to-many-relations#implicit-many-to-many-relations))

### Data modeling and migrations

Prisma models are defined in the [Prisma schema](/orm/prisma-schema) while TypeORM uses classes and experimental TypeScript decorators for model definitions. With the Active Record ORM pattern, TypeORM's approach often leads to complex model instances that are becoming hard to maintain as an application grows.

Prisma ORM on the other hand generates a lightweight database client that exposes a tailored and fully type-safe API to read and write data for the models that are defined in the Prisma schema, following the DataMapper ORM pattern rather than Active Record.

Prisma ORM's DSL for data modeling is lean, simple and intuitive to use. When modeling data in VS Code, you can further take advantage of Prisma ORM's powerful VS Code extension with features like autocompletion, quick fixes, jump to definition and other benefits that increase developer productivity.

<ParallelBlocks>

<block content="Prisma ORM">

```prisma
model User {
  id    Int     @id @default(autoincrement())
  name  String?
  email String  @unique
  posts Post[]
}

model Post {
  id        Int     @id @default(autoincrement())
  title     String
  content   String?
  published Boolean @default(false)
  authorId  Int?
  author    User?   @relation(fields: [authorId], references: [id])
}
```

</block>

<block content="TypeORM">

```ts
import {
  Entity,
  PrimaryGeneratedColumn,
  Column,
  OneToMany,
  ManyToOne,
} from 'typeorm'

@Entity()
export class User {
  @PrimaryGeneratedColumn()
  id: number

  @Column({ nullable: true })
  name: string

  @Column({ unique: true })
  email: string

  @OneToMany((type) => Post, (post) => post.author)
  posts: Post[]
}

@Entity()
export class Post {
  @PrimaryGeneratedColumn()
  id: number

  @Column()
  title: string

  @Column({ nullable: true })
  content: string

  @Column({ default: false })
  published: boolean

  @ManyToOne((type) => User, (user) => user.posts)
  author: User
}
```

</block>

</ParallelBlocks>

Migrations work in similar fashions in TypeORM and Prisma ORM. Both tools follow the approach of generating SQL files based on the provided model definitions and provide a CLI to execute them against the database. The SQL files can be modified before the migrations are executed so that any custom database operation can be performed with either migration system.

## Type safety

TypeORM has been one of the first ORMs in the Node.js ecosystem to fully embrace TypeScript and has done a great job in enabling developers to get a certain level of type safety for their database queries.

However, there are numerous situations where the type safety guarantees of TypeORM fall short. The following sections describe the scenarios where Prisma ORM can provide stronger guarantees for the types of query results.

### Selecting fields

This section explains the differences in type safety when selecting a subset of a model's fields in a query.

#### TypeORM

TypeORM provides a `select` option for its [`find`](https://typeorm.io/find-options) methods (e.g. `find`, `findByIds`, `findOne`, ...), for example:

<TabbedContent code>

<TabItem value="`find` with `select`">

```ts
const postRepository = getManager().getRepository(Post)
const publishedPosts: Post[] = await postRepository.find({
  where: { published: true },
  select: ['id', 'title'],
})
```

</TabItem>

<TabItem value="Model">

```ts
@Entity()
export class Post {
  @PrimaryGeneratedColumn()
  id: number

  @Column()
  title: string

  @Column({ nullable: true })
  content: string

  @Column({ default: false })
  published: boolean

  @ManyToOne((type) => User, (user) => user.posts)
  author: User
}
```

</TabItem>

</TabbedContent>

While each object in the returned `publishedPosts` array only carries the selected `id` and `title` properties at runtime, the TypeScript compiler doesn't have any knowledge of this. It will allow you to access any other properties defined on the `Post` entity after the query, for example:

```ts
const post = publishedPosts[0]

// The TypeScript compiler has no issue with this
if (post.content.length > 0) {
  console.log(`This post has some content.`)
}
```

This code will result in an error at runtime:

```
TypeError: Cannot read property 'length' of undefined
```

The TypeScript compiler only sees the `Post` type of the returned objects, but it doesn't know about the fields that these objects _actually_ carry at runtime. It therefore can't protect you from accessing fields that have not been retrieved in the database query, resulting in a runtime error.

#### Prisma ORM

Prisma Client can guarantee full type safety in the same situation and protects you from accessing fields that were not retrieved from the database.

Consider the same example with a Prisma Client query:

<TabbedContent code>

<TabItem value="`findMany` with `select`">

```ts
const publishedPosts = await prisma.post.findMany({
  where: { published: true },
  select: {
    id: true,
    title: true,
  },
})
const post = publishedPosts[0]

// The TypeScript compiler will not allow this
if (post.content.length > 0) {
  console.log(`This post has some content.`)
}
```

</TabItem>

<TabItem value="Model">

```prisma
model Post {
  id        Int     @id @default(autoincrement())
  title     String
  content   String?
  published Boolean @default(false)
  authorId  Int?
  author    User?   @relation(fields: [authorId], references: [id])
}
```

</TabItem>

</TabbedContent>

In this case, the TypeScript compiler will throw the following error already at compile-time:

```
[ERROR] 14:03:39 ⨯ Unable to compile TypeScript:
src/index.ts:36:12 - error TS2339: Property 'content' does not exist on type '{ id: number; title: string; }'.

42   if (post.content.length > 0) {
```

This is because Prisma Client generates the return type for its queries _on the fly_. In this case, `publishedPosts` is typed as follows:

```ts
const publishedPosts: {
  id: number
  title: string
}[]
```

It therefore is impossible for you to accidentally access a property on a model that has not been retrieved in a query.

### Loading relations

This section explains the differences in type safety when loading relations of a model in a query. In traditional ORMs, this is sometimes called _eager loading_.

#### TypeORM

TypeORM allows to eagerly load relations from the database via the `relations` option that can be passed to its [`find`](https://typeorm.io/find-options) methods.

Consider this example:

<TabbedContent code>

<TabItem value="`find` with `relations`">

```ts
const postRepository = getManager().getRepository(Post)
const publishedPosts: Post[] = await postRepository.find({
  where: { published: true },
  relations: ['author'],
})
```

</TabItem>

<TabItem value="Models">

```ts
@Entity()
export class Post {
  @PrimaryGeneratedColumn()
  id: number

  @Column()
  title: string

  @Column({ nullable: true })
  content: string

  @Column({ default: false })
  published: boolean

  @ManyToOne((type) => User, (user) => user.posts)
  author: User
}
```

```ts
@Entity()
export class User {
  @PrimaryGeneratedColumn()
  id: number

  @Column({ nullable: true })
  name: string

  @Column({ unique: true })
  email: string

  @OneToMany((type) => Post, (post) => post.author)
  posts: Post[]
}
```

</TabItem>

</TabbedContent>

Unlike with `select`, TypeORM does _not_ provide autocompletion, nor any type-safety for the strings that are passed to the `relations` option. This means, the TypeScript compiler is not able to catch any typos that are made when querying these relations. For example, it would allow for the following query:

```ts
const publishedPosts: Post[] = await postRepository.find({
  where: { published: true },
  // this query would lead to a runtime error because of a typo
  relations: ['authors'],
})
```

This subtle typo would now lead to the following runtime error:

```
UnhandledPromiseRejectionWarning: Error: Relation "authors" was not found; please check if it is correct and really exists in your entity.
```

#### Prisma ORM

Prisma ORM protects you from mistakes like this and thus eliminates a whole class of errors that can occur in your application at runtime. When using `include` to load a relation in a Prisma Client query, you can not only take advantage of autocompletion to specify the query, but the result of the query will also be properly typed:

<TabbedContent code>

<TabItem value="`find` with `relations`">

```ts
const publishedPosts = await prisma.post.findMany({
  where: { published: true },
  include: { author: true },
})
```

</TabItem>

<TabItem value="Models">

```ts
model User {
  id      Int      @id @default(autoincrement())
  name    String?
  email   String   @unique
  posts   Post[]
}

model Post {
  id                Int                @id @default(autoincrement())
  title             String
  content           String?
  published         Boolean            @default(false)
  authorId          Int?
  author            User?              @relation(fields: [authorId], references: [id])
}
```

</TabItem>

</TabbedContent>

Again, the type of `publishedPosts` is generated on the fly and looks as follows:

```ts
const publishedPosts: (Post & {
  author: User
})[]
```

For reference, this is what the `User` and `Post` types look like that Prisma Client generates for your Prisma models:

<TabbedContent code>

<TabItem value="`User`">

```ts
// Generated by Prisma ORM
export type User = {
  id: number
  name: string | null
  email: string
}
```

</TabItem>

<TabItem value="`Post`">

```ts
// Generated by Prisma ORM
export type Post = {
  id: number
  title: string
  content: string | null
  published: boolean
  authorId: number | null
}
```

</TabItem>

</TabbedContent>

### Filtering

This section explains the differences in type safety when filtering a list of records using `where`.

#### TypeORM

TypeORM allows to pass a `where` option to its [`find`](https://typeorm.io/find-options) methods to filter the list of returned records according to specific criteria. These criteria can be defined with respect to a model's properties.

##### Loosing type-safety using operators

Consider this example:

<TabbedContent code>

<TabItem value="`find` with `select`">

```ts
const postRepository = getManager().getRepository(Post)
const publishedPosts: Post[] = await postRepository.find({
  where: {
    published: true,
    title: ILike('Hello World'),
    views: MoreThan(0),
  },
})
```

</TabItem>

<TabItem value="Model">

```ts
@Entity()
export class Post {
  @PrimaryGeneratedColumn()
  id: number

  @Column()
  title: string

  @Column({ nullable: true })
  content: string

  @Column({ nullable: true })
  views: number

  @Column({ default: false })
  published: boolean

  @ManyToOne((type) => User, (user) => user.posts)
  author: User
}
```

</TabItem>

</TabbedContent>

This code runs properly and produces a valid query at runtime. However, the `where` option is not really type-safe in various different scenarios. When using a `FindOperator` like `ILike` or `MoreThan` that only work for specific types (`ILike` works for strings, `MoreThan` for numbers), you're losing the guarantee of providing the correct type for the model's field.

For example, you can provide a string to the `MoreThan` operator. The TypeScript compiler will not complain and your application will only fail at runtime:

```ts
const postRepository = getManager().getRepository(Post)
const publishedPosts: Post[] = await postRepository.find({
  where: {
    published: true,
    title: ILike('Hello World'),
    views: MoreThan('test'),
  },
})
```

The code above results in a runtime error that the TypeScript compiler doesn't catch for you:

```
error: error: invalid input syntax for type integer: "test"
```

##### Specifying non-existing properties

Also note that the TypeScript compiler allows you to specify properties on the `where` option that don't exist on your models – again resulting in runtime errors:

```ts
const publishedPosts: Post[] = await postRepository.find({
  where: {
    published: true,
    title: ILike('Hello World'),
    viewCount: 1,
  },
})
```

In this case, your application again fails at runtime with the following error:

```
EntityColumnNotFound: No entity column "viewCount" was found.
```

#### Prisma ORM

Both filtering scenarios that are problematic with TypeORM in terms of type-safety are covered by Prisma ORM in a fully type-safe way.

##### Type-safe usage of operators

With Prisma ORM, the TypeScript compiler enforces the correct usage of an operator per field:

```ts
const publishedPosts = await prisma.post.findMany({
  where: {
    published: true,
    title: { contains: 'Hello World' },
    views: { gt: 0 },
  },
})
```

It would not be allowed to specify the same problematic query shown above with Prisma Client:

```ts
const publishedPosts = await prisma.post.findMany({
  where: {
    published: true,
    title: { contains: 'Hello World' },
    views: { gt: 'test' }, // Caught by the TypeScript compiler
  },
})
```

The TypeScript compiler would catch this and throw the following error to protect you from a runtime failure of the app:

```
[ERROR] 16:13:50 ⨯ Unable to compile TypeScript:
src/index.ts:39:5 - error TS2322: Type '{ gt: string; }' is not assignable to type 'number | IntNullableFilter'.
  Type '{ gt: string; }' is not assignable to type 'IntNullableFilter'.
    Types of property 'gt' are incompatible.
      Type 'string' is not assignable to type 'number'.

42     views: { gt: "test" }
```

##### Type-safe definition of filters as model properties

With TypeORM, you are able to specify a property on the `where` option that doesn't map to a model's field. In the above example, filtering for `viewCount` therefore led to a runtime error because the field actually is called `views`.

With Prisma ORM, the TypeScript compiler will not allow to reference any properties inside of `where` that don't exist on the model:

```ts
const publishedPosts = await prisma.post.findMany({
  where: {
    published: true,
    title: { contains: 'Hello World' },
    viewCount: { gt: 0 }, // Caught by the TypeScript compiler
  },
})
```

Again, the TypeScript compiler complains with the following message to protect you from your own mistakes:

```ts
[ERROR] 16:16:16 ⨯ Unable to compile TypeScript:
src/index.ts:39:5 - error TS2322: Type '{ published: boolean; title: { contains: string; }; viewCount: { gt: number; }; }' is not assignable to type 'PostWhereInput'.
  Object literal may only specify known properties, and 'viewCount' does not exist in type 'PostWhereInput'.

42     viewCount: { gt: 0 }
```

### Creating new records

This section explains the differences in type safety when creating new records.

#### TypeORM

With TypeORM, there are two main ways to create new records in the database: `insert` and `save`. Both methods allow developers to submit data that can lead to runtime errors when _required_ fields are not provided.

Consider this example:

<TabbedContent code>

<TabItem value="Create with `save`">

```ts
const userRepository = getManager().getRepository(User)
const newUser = new User()
newUser.name = 'Alice'
userRepository.save(newUser)
```

</TabItem>

<TabItem value="Create with `insert`">

```ts
const userRepository = getManager().getRepository(User)
userRepository.insert({
  name: 'Alice',
})
```

</TabItem>

<TabItem value="Model">

```ts
@Entity()
export class User {
  @PrimaryGeneratedColumn()
  id: number

  @Column({ nullable: true })
  name: string

  @Column({ unique: true })
  email: string

  @OneToMany((type) => Post, (post) => post.author)
  posts: Post[]
}
```

</TabItem>

</TabbedContent>

No matter if you're using `save` or `insert` for record creation with TypeORM, you will get the following runtime error if you forget to provide the value for a required field:

```
QueryFailedError: null value in column "email" of relation "user" violates not-null constraint
```

The `email` field is defined as required on the `User` entity (which is enforced by a `NOT NULL` constraint in the database).

### Prisma ORM

Prisma ORM protects you from these kind of mistakes by enforcing that you submit values for _all_ required fields of a model.

For example, the following attempt to create a new `User` where the required `email` field is missing would be caught by the TypeScript compiler:

<TabbedContent code>

<TabItem value="Create with `create`">

```ts
const newUser = await prisma.user.create({
  data: {
    name: 'Alice',
  },
})
```

</TabItem>

<TabItem value="Model">

```prisma
model User {
  id    Int     @id @default(autoincrement())
  name  String?
  email String  @unique
}
```

</TabItem>

</TabbedContent>

It would lead to the following compile-time error:

```
[ERROR] 10:39:07 ⨯ Unable to compile TypeScript:
src/index.ts:39:5 - error TS2741: Property 'email' is missing in type '{ name: string; }' but required in type 'UserCreateInput'.
```

## API comparison

### Fetching single objects

**Prisma ORM**

```ts
const user = await prisma.user.findUnique({
  where: {
    id: 1,
  },
})
```

**TypeORM**

```ts
const userRepository = getRepository(User)
const user = await userRepository.findOne(id)
```

### Fetching selected scalars of single objects

**Prisma ORM**

```ts
const user = await prisma.user.findUnique({
  where: {
    id: 1,
  },
  select: {
    name: true,
  },
})
```

**TypeORM**

```ts
const userRepository = getRepository(User)
const user = await userRepository.findOne(id, {
  select: ['id', 'email'],
})
```

### Fetching relations

**Prisma ORM**

<TabbedContent code>
<TabItem value="Using include">

```ts
const posts = await prisma.user.findUnique({
  where: {
    id: 2,
  },
  include: {
    post: true,
  },
})
```

</TabItem>
<TabItem value="Fluent API">

```ts
const posts = await prisma.user
  .findUnique({
    where: {
      id: 2,
    },
  })
  .post()
```

</TabItem>
</TabbedContent>

> **Note**: `select` return a `user` object that includes a `post` array, whereas the fluent API only returns a `post` array.

**TypeORM**

<TabbedContent code>
<TabItem value="Using `relations`">

```ts
const userRepository = getRepository(User)
const user = await userRepository.findOne(id, {
  relations: ['posts'],
})
```

</TabItem>
<TabItem value="Using `JOIN`">

```ts
const userRepository = getRepository(User)
const user = await userRepository.findOne(id, {
  join: {
    alias: 'user',
    leftJoinAndSelect: {
      posts: 'user.posts',
    },
  },
})
```

</TabItem>
<TabItem value="Using earger relations">

```ts
const userRepository = getRepository(User)
const user = await userRepository.findOne(id)
```

</TabItem>
</TabbedContent>

### Filtering for concrete values

**Prisma ORM**

```ts
const posts = await prisma.post.findMany({
  where: {
    title: {
      contains: 'Hello',
    },
  },
})
```

**TypeORM**

```ts
const userRepository = getRepository(User)
const users = await userRepository.find({
  where: {
    name: 'Alice',
  },
})
```

### Other filter criteria

**Prisma ORM**

Prisma ORM generates many [additional filters](/orm/prisma-client/queries/filtering-and-sorting) that are commonly used in modern application development.

**TypeORM**

TypeORM provides [built-in operators](https://typeorm.io/find-options#advanced-options) that can be used to create more complex comparisons

### Relation filters

**Prisma ORM**

Prisma ORM lets you filter a list based on a criteria that applies not only to the models of the list being retrieved, but to a _relation_ of that model.

For example, the following query returns users with one or more posts with "Hello" in the title:

```ts
const posts = await prisma.user.findMany({
  where: {
    Post: {
      some: {
        title: {
          contains: 'Hello',
        },
      },
    },
  },
})
```

**TypeORM**

TypeORM doesn't offer a dedicated API for relation filters. You can get similar functionality by using the `QueryBuilder` or writing the queries by hand.

### Pagination

**Prisma ORM**

Cursor-style pagination:

```ts
const page = await prisma.post.findMany({
  before: {
    id: 242,
  },
  last: 20,
})
```

Offset pagination:

```ts
const cc = await prisma.post.findMany({
  skip: 200,
  first: 20,
})
```

**TypeORM**

```ts
const postRepository = getRepository(Post)
const posts = await postRepository.find({
  skip: 5,
  take: 10,
})
```

### Creating objects

**Prisma ORM**

```ts
const user = await prisma.user.create({
  data: {
    email: 'alice@prisma.io',
  },
})
```

**TypeORM**

<TabbedContent code>
<TabItem value="Using `save`">

```ts
const user = new User()
user.name = 'Alice'
user.email = 'alice@prisma.io'
await user.save()
```

</TabItem>
<TabItem value="Using `create`">

```ts
const userRepository = getRepository(User)
const user = await userRepository.create({
  name: 'Alice',
  email: 'alice@prisma.io',
})
await user.save()
```

</TabItem>
<TabItem value="Using `insert`">

```ts
const userRepository = getRepository(User)
await userRepository.insert({
  name: 'Alice',
  email: 'alice@prisma.io',
})
```

</TabItem>
</TabbedContent>

### Updating objects

**Prisma ORM**

```ts
const user = await prisma.user.update({
  data: {
    name: 'Alicia',
  },
  where: {
    id: 2,
  },
})
```

**TypeORM**

```ts
const userRepository = getRepository(User)
const updatedUser = await userRepository.update(id, {
  name: 'James',
  email: 'james@prisma.io',
})
```

### Deleting objects

**Prisma ORM**

```ts
const deletedUser = await prisma.user.delete({
  where: {
    id: 10,
  },
})
```

**TypeORM**

<TabbedContent code>
<TabItem value="Using `delete`">

```ts
const userRepository = getRepository(User)
await userRepository.delete(id)
```

</TabItem>
<TabItem value="Using `remove`">

```ts
const userRepository = getRepository(User)
const deletedUser = await userRepository.remove(user)
```

</TabItem>
</TabbedContent>

### Batch updates

**Prisma ORM**

```ts
const user = await prisma.user.updateMany({
  data: {
    name: 'Published author!',
  },
  where: {
    Post: {
      some: {
        published: true,
      },
    },
  },
})
```

**TypeORM**

You can use the [query builder to update entities in your database](https://typeorm.io/update-query-builder).

### Batch deletes

**Prisma ORM**

```ts
const users = await prisma.user.deleteMany({
  where: {
    id: {
      in: [1, 2, 6, 6, 22, 21, 25],
    },
  },
})
```

**TypeORM**

<TabbedContent code>
<TabItem value="Using `delete`">

```ts
const userRepository = getRepository(User)
await userRepository.delete([id1, id2, id3])
```

</TabItem>
<TabItem value="Using `remove`">

```ts
const userRepository = getRepository(User)
const deleteUsers = await userRepository.remove([user1, user2, user3])
```

</TabItem>
</TabbedContent>

### Transactions

**Prisma ORM**

```ts
const user = await prisma.user.create({
  data: {
    email: 'bob.rufus@prisma.io',
    name: 'Bob Rufus',
    Post: {
      create: [
        { title: 'Working at Prisma' },
        { title: 'All about databases' },
      ],
    },
  },
})
```

**TypeORM**

```ts
await getConnection().$transaction(async (transactionalEntityManager) => {
  const user = getRepository(User).create({
    name: 'Bob',
    email: 'bob@prisma.io',
  })
  const post1 = getRepository(Post).create({
    title: 'Join us for GraphQL Conf in 2019',
  })
  const post2 = getRepository(Post).create({
    title: 'Subscribe to GraphQL Weekly for GraphQL news',
  })
  user.posts = [post1, post2]
  await transactionalEntityManager.save(post1)
  await transactionalEntityManager.save(post2)
  await transactionalEntityManager.save(user)
})
```
