使用TypeORM
并联接为Postgres
数据库设置的表时,我遇到了一个非常有趣的问题。我想通了,但认为我会将信息发布给其他有类似问题的人。
我在数据库中设置了3个表:user
,organisation
,user_organisation
。
其目的是用户可以属于许多组织,名为user_organisation
的表将用户映射到这些组织。所以我的实体看起来像这样,
user.entity.ts
import { TimestampedEntity } from '@shared/entities/timestamped.entity';
import { Organisation } from '@user/entities/organisation.entity';
import { UserOrganisation } from '@user/entities/user-organisation.entity';
import { Column, Entity, Index, JoinTable, ManyToMany, OneToMany, PrimaryGeneratedColumn } from 'typeorm';
@Entity()
@Index(['email', 'password'])
export class User extends TimestampedEntity {
@PrimaryGeneratedColumn()
userId: number;
@Column({
length: 64
})
username: string;
@Column({
length: 500
})
email: string;
@Column({
length: 255
})
password: string;
@Column({
type: 'json',
})
details: any;
@Column({
nullable: true
})
refreshToken: string;
@OneToMany(type => UserOrganisation, userOrganisation => userOrganisation.user)
@JoinTable()
userOrganisations: UserOrganisation[];
}
user-organisation.entity.ts
import { Organisation } from '@user/entities/organisation.entity';
import { User } from '@user/entities/user.entity';
import { Column, Entity, JoinColumn, ManyToOne, OneToOne, PrimaryColumn, PrimaryGeneratedColumn } from 'typeorm';
@Entity()
export class UserOrganisation {
@ManyToOne(type => User, user => user.userOrganisations, { primary: true })
user: User;
@ManyToOne(type => Organisation, organisation => organisation.userOrganisations, { primary: true })
organisation: Organisation;
}
organization.entity.ts
import { TimestampedEntity } from '@shared/entities/timestamped.entity';
import { UserOrganisation } from '@user/entities/user-organisation.entity';
import { User } from '@user/entities/user.entity';
import { Column, Entity, JoinColumn, JoinTable, ManyToMany, ManyToOne, OneToMany, OneToOne, PrimaryGeneratedColumn } from 'typeorm';
@Entity()
export class Organisation extends TimestampedEntity {
@PrimaryGeneratedColumn()
orgId: number;
@Column({
length: 255
})
name: string;
@Column({
type: 'json'
})
details: any;
@OneToMany(type => UserOrganisation, userOrganisation => userOrganisation.organisation)
userOrganisations: UserOrganisation[];
}
然后我试图运行以下查询,
this.userRepository.createQueryBuilder('user')
.where('user.email = :email', { email })
.innerJoin(UserOrganisation, 'userOrganisation', 'user.userId = userOrganisation.userUserId')
.getOne();
这是我收到的错误消息,
ERROR: missing FROM-clause entry for table "userorganisation" at character 401
最终的查询像这样打印出来,
SELECT "user"."createdAt" AS "user_createdAt", "user"."updatedAt" AS "user_updatedAt", "user"."userId" AS "user_userId", "user"."username" AS "user_username", "user"."email" AS "user_email", "user"."password" AS "user_password", "user"."details" AS "user_details", "user"."refreshToken" AS "user_refreshToken" FROM "user" "user" INNER JOIN "user_organisation" "userOrganisation" ON "user"."userId" = userOrganisation.userUserId WHERE "user"."email" = $1
我修复它的方法如下所述。
答案 0 :(得分:1)
做得好。但是,在typeorm中使用联接时,必须先编写定义的条件,然后设置对象。
this.userRepository.createQueryBuilder('user')
.where('user.email = :email', { email })
.innerJoin(UserOrganisation, 'userOrganisation', 'user.userId=userOrganisation.user.userId')
.getOne();
为此,您无需添加引号。
生成的sql不显示引号,因为它不知道如何填充条件。
我希望这会有所帮助。
答案 1 :(得分:0)
我在查询中发现的内容
SELECT "user"."createdAt" AS "user_createdAt", "user"."updatedAt" AS "user_updatedAt", "user"."userId" AS "user_userId", "user"."username" AS "user_username", "user"."email" AS "user_email", "user"."password" AS "user_password", "user"."details" AS "user_details", "user"."refreshToken" AS "user_refreshToken" FROM "user" "user" INNER JOIN "user_organisation" "userOrganisation" ON "user"."userId" = userOrganisation.userUserId WHERE "user"."email" = $1
联接条件中的user
表和userOrganisation
表之间是否存在差异,
"user"."userId" = userOrganisation.userUserId
user
表会自动用引号引起来,但userOrganisation
却没有...所以我将代码更改为以下代码,
this.userRepository.createQueryBuilder('user')
.where('user.email = :email', { email })
.innerJoin(UserOrganisation, 'userOrganisation', '"user"."userId" = "userOrganisation"."userUserId"')
.getOne();
如果您在上面查看,我已经在连接条件中添加了引号。现在都在工作:)
希望这会有所帮助!