環境
再現コード
function findOneByBarAndId(
bar: Bar
id: number // foo の id (コード内参照)
): Promise<Foo | undefined> {
const queryBuilder = this.fooRepo
.createQueryBuilder('foo')
.innerJoinAndSelect('foo.bars', 'bar')
.where('foo.id = :id', { id })
.andWhere('bar.id = :id', { id: bar.id }) // ここに地雷があります
.getOne()
}
地雷
id
が被っているため、前の id
の値も後の値(ここでは bar.id
)が使われてしまいます。
最初のプレースホルダー部分を { id: id }
としても駄目です。
DBのログを有効(logging: true
)にして、 同じ値が使われていたのを見て気が付きました。
地雷回避方法
プレースホルダー名を変えましょう。
- .andWhere('bar.id = :id', { id: bar.id }) // 地雷
+ .andWhere('bar.id = :barId', { barId: bar.id }) // 回避
ドキュメント
https://github.com/typeorm/typeorm/blob/master/docs/select-query-builder.md#using-subqueries
に書かれていました。
Note: do not use the same parameter name for different values across the query builder. Values will be overridden if you set them multiple times.