Michael
Michael

Reputation: 607

Doctrine 2 insists on persisting already managed entity in ManyToOne relationship

I have a database table containing departments. I have another table containing people. As you'd expect a department contains many people, and a person is in a single department.

When I want to persist a new person to the database, I create a Person object and try to set it's Department property to an existing Department object which is managed by the Entity Manager. However, when I try to persist my new Person, I get an exception:

A new entity was found through the relationship 'Entities\Person#department' that was not configured to cascade persist operations for entity: Entities\Department@0000000016abe202000000000d29dd37. To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity or configure cascade persist this association in the mapping for example @ManyToOne(..,cascade={"persist"}).

I don't fully understand the part of the exception which says the department is an "unknown entity", since I extracted it via the Entity manager.

As the exception suggests, I inserted a cascade into the yml metadata (cascade: ["persist"]). My person then gets saved, but I end up with a duplicated Department in the departments table, with a new id.

This must be a very common use case. I've included my code and metadata below. What changes should I make?

Metadata:

Entities\Person
  type: entity
  table: people
  fields:
    ...
    departmentId:
      type: integer
      unsigned: false
      nullable: false
      column: department_id
    ...
  manyToOne:
    department:
      targetEntity: Entities\Department
      joinColumn: department_id
      referenceColumnName: id

Code:

$department = $em->getRepository('Department')->findOneBy(array('name' => $departmentName);

$person = new Person();
$person->setName('Joe Bloggs');
$person->setDepartment($department);

$em->persist($person);
$em->flush();

Upvotes: 8

Views: 4771

Answers (1)

Michael
Michael

Reputation: 607

The problem was caused by using different instances of the Entity Manager to first fetch the department, and then persist the Person.

My entity manager is now a singleton, so whichever class requests an entity manager gets the same instance.

Upvotes: 11

Related Questions