Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeORM- findOne returns unexpected value

I have a User Entity with an Email Column. When I use TypeORM's findOne function to search for a Email which doesn't exist in the database, findOne returns the first entry to the User Entity for some reason. This function seems not to work like in the documentation.

findOne:

// returns the first User of database
const user = await this.userRepository.findOne({ email: '[email protected]' });

User.Entity.ts:

import {
  Entity,
  Column,
  PrimaryGeneratedColumn,
} from 'typeorm';

@Entity()
export class User {
  @PrimaryGeneratedColumn({ name: 'id' })
  private _id: number;

  @Column({ name: 'password', length: 256, nullable: true })
  private _password?: string;

  @Column({ name: 'email', length: 300, nullable: true, unique: true })
  private _email?: string;

  @Column({ name: 'roles', length: 300, nullable: true })
  private _roles?: string = null;

  public get id(): number {
    return this._id;
  }

  public set id(id: number) {
    this._id = id;
  }

  public get email(): string {
    return this._email;
  }

  public set email(email: string) {
    this._email = email;
  }

  public get password(): string {
    return this._password;
  }

  public set password(password: string) {
    this._password = password;
  }

  public get roles(): string {
    return this._roles;
  }

  public set roles(roles: string) {
    this._roles = roles;
  }
}

This is from the official documentation:

const user = new User(); user.firstName = "Timber"; user.lastName = "Saw"; user.age = 25; await repository.save(user);

const allUsers = await repository.find(); const firstUser = await repository.findOne(1); // find by id const timber = await repository.findOne({ firstName: "Timber", lastName: "Saw" });

await repository.remove(timber);

like image 223
bonblow Avatar asked Nov 24 '18 05:11

bonblow


People also ask

What does findOne return TypeORM?

find will return an array, you should check the length of the array to confirm the rows match the WHERE clause executed. What happens with the current findOne implementation is that when a row is not found with the required values, the first row of the table in question is being returned. Hope this helps!

What is TypeORM?

TypeORM is a TypeScript ORM (object-relational mapper) library that makes it easy to link your TypeScript application up to a relational database database. TypeORM supports MySQL, SQlite, Postgres, MS SQL Server, and a host of other traditional options.


2 Answers

Works for me:

const user = await this.userRepository.findOne(
    { where:
        { email: '[email protected]' }
    }
);
like image 200
chavy Avatar answered Sep 20 '22 09:09

chavy


Since User.email property is a function and not a string, your findOne query essentially tries to find an entity whose email function equals '[email protected]' which naturally doesn't work. The actual email column in your model is _email, which as a private property cannot be referenced to in a TypeORM query.

There's a couple of options here:

  1. Get rid of your getters and setters. TypeORM does not support this form of encapsulation. Instead you can wrap your TypeORM Entity class with another domain model class for encapsulation, or if you're using getters/setters to transform values before db insert/select you could use TypeORM's value transformers instead.

  2. Use QueryBuilder for your queries instead of the find/findOne/etc methods. QueryBuilder can refer to any arbitrary column.

like image 39
Aleksi Avatar answered Sep 22 '22 09:09

Aleksi