I need help. I'm developing an API using Express and NodeJS with TypeScript, and I'm using TypeORM for database operations. I'm trying to create a function where I list and return all the appointments that were made by a specific user, but this error keeps happening and I don't know why. I have searched for an answer and read some StackOverflow questions and answers, but nothing worked, and that's why I decide to ask for help.
Exception has occurred: QueryFailedError: Unknown column 'NaN' in 'where clause' at QueryFailedError.TypeORMError [as constructor] (D:\Pessoal\Vinicius\TCC\hexperience-api\src\error\TypeORMError.ts:7:9) at new QueryFailedError (D:\Pessoal\Vinicius\TCC\hexperience-api\src\error\QueryFailedError.ts:9:9) at Query.onResult (D:\Pessoal\Vinicius\TCC\hexperience-api\src\driver\mysql\MysqlQueryRunner.ts:195:37) at Query.execute (D:\Pessoal\Vinicius\TCC\hexperience-api\node_modules\mysql2\lib\commands\command.js:31:14) at PoolConnection.handlePacket (D:\Pessoal\Vinicius\TCC\hexperience-api\node_modules\mysql2\lib\connection.js:456:32) at PacketParser.onPacket (D:\Pessoal\Vinicius\TCC\hexperience-api\node_modules\mysql2\lib\connection.js:85:12) at PacketParser.executeStart (D:\Pessoal\Vinicius\TCC\hexperience-api\node_modules\mysql2\lib\packet_parser.js:75:16) at Socket. (D:\Pessoal\Vinicius\TCC\hexperience-api\node_modules\mysql2\lib\connection.js:92:25) at Socket.emit (events.js:315:20) at addChunk (internal/streams/readable.js:309:12) at readableAddChunk (internal/streams/readable.js:284:9) at Socket.Readable.push (internal/streams/readable.js:223:10) at TCP.onStreamRead (internal/stream_base_commons.js:188:23) at TCP.callbackTrampoline (internal/async_hooks.js:131:14)
Here is the code:
User.ts
import {Entity, Column, PrimaryGeneratedColumn, CreateDateColumn, UpdateDateColumn, OneToOne} from 'typeorm';
import { Exclude } from 'class-transformer';
import Host from './Host';
export enum typeEnum {
user = 'user',
host = 'host',
admin = 'admin'
}
@Entity('User')
class User {
@PrimaryGeneratedColumn('increment')
id: number;
@Column()
name: string;
@Column()
email: string;
@Column()
@Exclude()
password: string;
@Column()
avatar: string;
@Column()
phone_number: string;
@Column()
bio: string;
@Column({ type: 'boolean' })
is_blocked: boolean;
@Column({
type: 'enum',
enum: typeEnum,
default: typeEnum.user
})
type: typeEnum;
@CreateDateColumn()
created_at: Date;
@UpdateDateColumn()
updated_at: Date;
@OneToOne(type => Host, host => host.user)
host: Host;
}
export default User;
Appointment.ts
import {Column,Entity,PrimaryGeneratedColumn,CreateDateColumn,UpdateDateColumn,ManyToOne,JoinColumn} from "typeorm";
import Schedule from "../../../../experiences/infra/typeorm/entities/Schedule";
import User from "../../../../users/infra/typeorm/entities/User";
@Entity('Appointment')
class Appointment {
@PrimaryGeneratedColumn('increment')
id: number;
@Column()
guests: number;
@Column({ type: 'boolean' })
paid: boolean;
@Column({ type: 'decimal', precision: 12, scale: 2 })
final_price: number;
@CreateDateColumn()
created_at: Date;
@UpdateDateColumn()
updated_at: Date;
@ManyToOne(() => User)
@JoinColumn({ name: 'user_id' })
user: User;
@ManyToOne(() => Schedule)
@JoinColumn({ name: 'schedule_id' })
schedule: Schedule;
}
export default Appointment;
AppointmentsRepository.ts
import { getRepository, Repository } from "typeorm";
import Appointment from "../entities/Appointment";
import IAppointmentsRepository from "@modules/appointments/repositories/IAppointmentsRepository";
import ICreateAppointmentDTO from "@modules/appointments/dtos/ICreateAppointmentDTO";
class AppointmentsRepository implements IAppointmentsRepository {
private ormRepository: Repository<Appointment>;
constructor () {
this.ormRepository = getRepository(Appointment);
}
// this function has the same idea as the one that has the problem but this one works normally
public async findByExperienceId(exp_id: number): Promise<Appointment[]> {
const appointments = await this.ormRepository.find({
relations: ['user', 'schedule', 'schedule.experience'],
where: {
schedule: {
experience: {
id: exp_id,
}
}
}
});
return appointments
}
// here is the function with the problem
public async findByUserId(user_id: number): Promise<Appointment[]> {
// this was my last attempt to fix the problem, didn't work
const appointments = await this.ormRepository.query(
'SELECT * FROM Appointment a ' +
'LEFT JOIN `User` u ON u.id = a.user_id ' +
'LEFT JOIN Schedule s ON s.id = a.schedule_id ' +
'LEFT JOIN Experience e ON e.id = s.exp_id ' +
'WHERE a.user_id = ' + Number(user_id)
);
// This was the original code
// const appointments = await this.ormRepository.find({
// relations: ['user', 'schedule', 'schedule.experience'],
// where: {
// user: {
// id: user_id
// }
// }
// });
return appointments;
}
}
export default AppointmentsRepository;
ListUserAppointmentsService.ts
import { inject, injectable } from "tsyringe";
import AppError from "@shared/errors/AppError";
import Appointment from "../infra/typeorm/entities/Appointment";
import IUsersRepository from "@modules/users/repositories/IUsersRepository";
import IAppointmentsRepository from "../repositories/IAppointmentsRepository";
interface IRequest {
id: number
}
@injectable()
class ListUserAppointmentsService {
constructor (
@inject('UsersRepository')
private usersRepository: IUsersRepository,
@inject('AppointmentsRepository')
private appointmentsRepository: IAppointmentsRepository
) {}
public async execute({ id }: IRequest): Promise<Appointment[]> {
const user = await this.usersRepository.findById(id);
if (!user) {
throw new AppError('User does not exists');
}
// originally, I was passing the parameter id
const appointments = await this.appointmentsRepository.findByUserId(user.id);
return appointments;
}
}
export default ListUserAppointmentsService;