-
-
Notifications
You must be signed in to change notification settings - Fork 6.5k
Description
Issue description
TypeORM 0.3.26 appears to have changed behavior for many-to-many relationships when user-defined junction entities exist. The relationship data is not being persisted correctly, with junction table rows containing NULL values instead of the expected foreign key relationships.
Expected Behavior
In TypeORM <=0.3.25, junction table should be populated with proper foreign key values:
INSERT INTO "vet_specialty"("vet_id", "specialty_name") VALUES ($1, $2), ($3, $4) -- PARAMETERS: [1,"dogs",1,"cats"]
Junction table contains relationship data, queries return related entities.
> npm install typeorm@0.3.25 --no-save && npm test
changed 1 package, and audited 140 packages in 1s
found 0 vulnerabilities
> type-orm-repro@1.0.0 test
> ts-node test.ts
query: SELECT version()
query: SELECT * FROM current_schema()
query: SELECT "Specialty"."name" AS "Specialty_name" FROM "specialty" "Specialty" WHERE "Specialty"."name" IN ($1, $2) -- PARAMETERS: ["dogs","cats"]
query: START TRANSACTION
query: INSERT INTO "specialty"("name") VALUES ($1), ($2) -- PARAMETERS: ["dogs","cats"]
query: COMMIT
query: SELECT "Specialty"."name" AS "Specialty_name" FROM "specialty" "Specialty" WHERE "Specialty"."name" IN ($1, $2) -- PARAMETERS: ["dogs","cats"]
query: START TRANSACTION
query: INSERT INTO "vet"("name") VALUES ($1) RETURNING "id" -- PARAMETERS: ["Carlos Salazar"]
query: INSERT INTO "vet_specialty"("vet_id", "specialty_name") VALUES ($1, $2), ($3, $4) -- PARAMETERS: [1,"dogs",1,"cats"]
query: COMMIT
query: SELECT DISTINCT "distinctAlias"."Vet_id" AS "ids_Vet_id" FROM (SELECT "Vet"."id" AS "Vet_id", "Vet"."name" AS "Vet_name", "Vet__Vet_specialties"."name" AS "Vet__Vet_specialties_name" FROM "vet" "Vet" LEFT JOIN "vet_specialty" "Vet_Vet__Vet_specialties" ON "Vet_Vet__Vet_specialties"."vet_id"="Vet"."id" LEFT JOIN "specialty" "Vet__Vet_specialties" ON "Vet__Vet_specialties"."name"="Vet_Vet__Vet_specialties"."specialty_name" WHERE (("Vet"."id" = $1))) "distinctAlias" ORDER BY "Vet_id" ASC LIMIT 1 -- PARAMETERS: [1]
query: SELECT "Vet"."id" AS "Vet_id", "Vet"."name" AS "Vet_name", "Vet__Vet_specialties"."name" AS "Vet__Vet_specialties_name" FROM "vet" "Vet" LEFT JOIN "vet_specialty" "Vet_Vet__Vet_specialties" ON "Vet_Vet__Vet_specialties"."vet_id"="Vet"."id" LEFT JOIN "specialty" "Vet__Vet_specialties" ON "Vet__Vet_specialties"."name"="Vet_Vet__Vet_specialties"."specialty_name" WHERE ( (("Vet"."id" = $1)) ) AND ( "Vet"."id" IN (1) ) -- PARAMETERS: [1]
Vet specialties count: 2
Expected: 2, Actual: 2
> psql -d postgres -c "SELECT * FROM vet_specialty"
id | vet_id | specialty_name
----+--------+----------------
1 | 1 | dogs
2 | 1 | cats
(2 rows)Actual Behavior
In TypeORM >=0.3.26, junction table gets rows with NULL/DEFAULT values:
INSERT INTO "vet_specialty"("vet_id", "specialty_name") VALUES (DEFAULT, DEFAULT), (DEFAULT, DEFAULT) RETURNING "id"Junction table contains empty rows, queries return no related entities.
> npm install typeorm@0.3.26 --no-save && npm test
changed 1 package, and audited 140 packages in 933ms
found 0 vulnerabilities
> type-orm-repro@1.0.0 test
> ts-node test.ts
query: SELECT version()
query: SELECT * FROM current_schema()
query: SELECT "Specialty"."name" AS "Specialty_name" FROM "specialty" "Specialty" WHERE "Specialty"."name" IN ($1, $2) -- PARAMETERS: ["dogs","cats"]
query: START TRANSACTION
query: INSERT INTO "specialty"("name") VALUES ($1), ($2) -- PARAMETERS: ["dogs","cats"]
query: COMMIT
query: SELECT "Specialty"."name" AS "Specialty_name" FROM "specialty" "Specialty" WHERE "Specialty"."name" IN ($1, $2) -- PARAMETERS: ["dogs","cats"]
query: START TRANSACTION
query: INSERT INTO "vet"("name") VALUES ($1) RETURNING "id" -- PARAMETERS: ["Carlos Salazar"]
query: INSERT INTO "vet_specialty"("vet_id", "specialty_name") VALUES (DEFAULT, DEFAULT), (DEFAULT, DEFAULT) RETURNING "id"
query: COMMIT
query: SELECT DISTINCT "distinctAlias"."Vet_id" AS "ids_Vet_id" FROM (SELECT "Vet"."id" AS "Vet_id", "Vet"."name" AS "Vet_name", "Vet__Vet_specialties"."name" AS "Vet__Vet_specialties_name" FROM "vet" "Vet" LEFT JOIN "vet_specialty" "Vet_Vet__Vet_specialties" ON "Vet_Vet__Vet_specialties"."vet_id"="Vet"."id" LEFT JOIN "specialty" "Vet__Vet_specialties" ON "Vet__Vet_specialties"."name"="Vet_Vet__Vet_specialties"."specialty_name" WHERE (("Vet"."id" = $1))) "distinctAlias" ORDER BY "Vet_id" ASC LIMIT 1 -- PARAMETERS: [1]
query: SELECT "Vet"."id" AS "Vet_id", "Vet"."name" AS "Vet_name", "Vet__Vet_specialties"."name" AS "Vet__Vet_specialties_name" FROM "vet" "Vet" LEFT JOIN "vet_specialty" "Vet_Vet__Vet_specialties" ON "Vet_Vet__Vet_specialties"."vet_id"="Vet"."id" LEFT JOIN "specialty" "Vet__Vet_specialties" ON "Vet__Vet_specialties"."name"="Vet_Vet__Vet_specialties"."specialty_name" WHERE ( (("Vet"."id" = $1)) ) AND ( "Vet"."id" IN (1) ) -- PARAMETERS: [1]
Vet specialties count: 0
Expected: 2, Actual: 0
> psql -d postgres -c "SELECT * FROM vet_specialty"
id | vet_id | specialty_name
----+--------+----------------
1 | |
2 | |
(2 rows)Steps to reproduce
Minimal reproducer available at danielfrankcom/typeorm-repro.
The reproducer includes a simple many-to-many relationship with a user-defined junction entity. Running the test with TypeORM 0.3.25 vs 0.3.26 shows the different behavior.
If the vet_specialty table is created in migration.sql but the VetSpecialty entity is not defined in entities.ts, the junction table works and produces the expected result. The existence of the junction table entity seems to cause the difference in behavior.
My Environment
| Dependency | Version |
|---|---|
| Operating System | MacOS |
| Node.js version | v22.18.0 |
| Typescript version | 5.9.2 |
| TypeORM version | 0.3.26 |
Additional Context
This behavior change appears to be related to PR #11114, which addressed duplicate metadata issues for user-defined junction tables. The change may have affected how junction metadata is created when explicit junction entities are present.
Relevant Database Driver(s)
- aurora-mysql
- aurora-postgres
- better-sqlite3
- cockroachdb
- cordova
- expo
- mongodb
- mysql
- nativescript
- oracle
- postgres
- react-native
- sap
- spanner
- sqlite
- sqlite-abstract
- sqljs
- sqlserver
Are you willing to resolve this issue by submitting a Pull Request?
No, I don’t have the time and I’m okay to wait for the community / maintainers to resolve this issue.