Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error with entities using composite key and one to many relationship. 'Error: Trying to query by not existing property OrderEvent.orderId' #3543

Closed
jbw opened this issue Sep 26, 2022 · 2 comments
Labels
bug Something isn't working

Comments

@jbw
Copy link

jbw commented Sep 26, 2022

Code to reproduce and instructions are in the following repo: https://github.com/jbw/composite-key-one-to-many-relationship

Expected behavior

  • Removing items from the collection and persisting the entity should remove the items from the database.

What happens

  • Error is produced when persisting the entity. See further below for stack trace.

Relevant code

Entities with composite key and one to many relationship (order 1-* orderItem):

Code which removes items from the order.events collection

Steps to reproduce

1. Create a postgresql database in Docker

docker run \
    -p 5455:5432 \
    -e POSTGRES_USER=postgres \
    -e POSTGRES_PASSWORD=postgres \
    -e POSTGRES_DB=composite-key-one-to-many-relationship-data \
    -d postgres

2. Apply migrations

 npx mikro-orm migration:fresh

3. Run the tests

yarn test

Error produced

Following is the error produced when running the test:

[Nest] 70996  - 26/09/2022, 21:09:53   ERROR [ExceptionsHandler] Trying to query by not existing property OrderEvent.orderId
Error: Trying to query by not existing property OrderEvent.orderId
    at /Users/jbw/code/composite-key-one-to-many-relationship/node_modules/@mikro-orm/knex/query/CriteriaNode.js:28:27
    at Array.forEach (<anonymous>)
    at new CriteriaNode (/Users/jbw/code/composite-key-one-to-many-relationship/node_modules/@mikro-orm/knex/query/CriteriaNode.js:23:17)
    at new ScalarCriteriaNode (/Users/jbw/code/composite-key-one-to-many-relationship/node_modules/@mikro-orm/knex/query/ScalarCriteriaNode.js:9:1)
    at Function.createScalarNode (/Users/jbw/code/composite-key-one-to-many-relationship/node_modules/@mikro-orm/knex/query/CriteriaNodeFactory.js:25:22)
    at Function.createNode (/Users/jbw/code/composite-key-one-to-many-relationship/node_modules/@mikro-orm/knex/query/CriteriaNodeFactory.js:22:21)
    at Function.createObjectItemNode (/Users/jbw/code/composite-key-one-to-many-relationship/node_modules/@mikro-orm/knex/query/CriteriaNodeFactory.js:54:25)
    at /Users/jbw/code/composite-key-one-to-many-relationship/node_modules/@mikro-orm/knex/query/CriteriaNodeFactory.js:45:28
    at Array.reduce (<anonymous>)
    at Function.createObjectNode (/Users/jbw/code/composite-key-one-to-many-relationship/node_modules/@mikro-orm/knex/query/CriteriaNodeFactory.js:44:45)

Removing orphanRemoval: true from the Order entity produces a different error.

diff --git a/src/order.entity.ts b/src/order.entity.ts
index 186d6de..937d4f0 100644
--- a/src/order.entity.ts
+++ b/src/order.entity.ts
@@ -14,9 +14,7 @@ export class Order {
   @PrimaryKey()
   companyId: string;

-  @OneToMany(() => OrderEvent, (orderEvent) => orderEvent.order, {
-    orphanRemoval: true,
-  })
+  @OneToMany(() => OrderEvent, (orderEvent) => orderEvent.order)
   events = new Collection<OrderEvent>(this);

Rerun tests and the following error is produced:

TypeError: Cannot read properties of undefined (reading '0')
    at /Users/jbw/code/composite-key-one-to-many-relationship/node_modules/@mikro-orm/knex/AbstractSqlDriver.js:343:88
    at Array.forEach (<anonymous>)
    at /Users/jbw/code/composite-key-one-to-many-relationship/node_modules/@mikro-orm/knex/AbstractSqlDriver.js:333:23
    at Array.forEach (<anonymous>)
    at /Users/jbw/code/composite-key-one-to-many-relationship/node_modules/@mikro-orm/knex/AbstractSqlDriver.js:331:29
    at Set.forEach (<anonymous>)
    at PostgreSqlDriver.nativeUpdateMany (/Users/jbw/code/composite-key-one-to-many-relationship/node_modules/@mikro-orm/knex/AbstractSqlDriver.js:329:14)
    at ChangeSetPersister.persistManagedEntitiesBatch (/Users/jbw/code/composite-key-one-to-many-relationship/node_modules/@mikro-orm/core/unit-of-work/ChangeSetPersister.js:174:27)
    at processTicksAndRejections (node:internal/process/task_queues:96:5)
    at ChangeSetPersister.persistManagedEntities (/Users/jbw/code/composite-key-one-to-many-relationship/node_modules/@mikro-orm/core/unit-of-work/ChangeSetPersister.js:147:13)

mikro-orm version is 5.4.2

@jbw
Copy link
Author

jbw commented Oct 17, 2022

Any help with this?

@B4nan
Copy link
Member

B4nan commented Oct 23, 2022

Next time I would appreciate simpler reproductions, not complex web apps with migrations and unrelated stuff to the thing you are actually trying to showcase. You will always get faster response if you do that, it took me 30 minutes to prepare a test case from your repro.

Removing orphanRemoval: true from the Order entity produces a different error.

If you would do that, it means removing items from collection nulls the owning side, but you define that as non-null and primary key, so that would be invalid even without the runtime error. You'd have to make the Event.order a nullable property (hence not a PK).

FYI this is the test minimal test case I'd hope you provide directly:

import { Collection, Entity, ManyToOne, OneToMany, OptionalProps, PrimaryKey, Property } from '@mikro-orm/core';
import { MikroORM } from '@mikro-orm/postgresql';
import { v4 } from 'uuid';

@Entity()
export class Order {

  [OptionalProps]?: 'orderId';

  @PrimaryKey()
  orderId: string = v4();

  @PrimaryKey()
  customerId!: string;

  @PrimaryKey()
  companyId!: string;

  @OneToMany(() => OrderEvent, orderEvent => orderEvent.order, { orphanRemoval: true })
  events = new Collection<OrderEvent>(this);

}

@Entity()
export class OrderEvent {

  [OptionalProps]?: 'orderEventId' | 'order';

  @PrimaryKey()
  orderEventId: string = v4();

  @Property()
  name!: string;

  @ManyToOne(() => Order, { primary: true })
  order!: Order;

}

let orm: MikroORM;

beforeAll(async () => {
  orm = await MikroORM.init({
    entities: [Order, OrderEvent],
    dbName: 'mikro_orm_test_3543',
  });
  await orm.schema.refreshDatabase();
});

afterAll(() => orm.close(true));

test('GH issue 3543', async () => {
  let order = orm.em.create(Order, {
    customerId: '456',
    companyId: '789',
  });

  order.events.add(orm.em.create(OrderEvent, { name: 'created' }));
  order.events.add(orm.em.create(OrderEvent, { name: 'pending' }));

  await orm.em.persistAndFlush(order);
  orm.em.clear();

  order = await orm.em.findOneOrFail(Order, {
    customerId: '456',
    companyId: '789',
    orderId: order.orderId,
  }, { populate: true });

  order.events.removeAll();
  await orm.em.flush();
  orm.em.clear();

  order = await orm.em.findOneOrFail(Order, {
    customerId: '456',
    companyId: '789',
    orderId: order.orderId,
  }, { populate: true });

  expect(order.events).toHaveLength(0);
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants