Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dealing with a closed EntityManager with Bisna/Doctrine2

So after an integrity constraint violation using Doctrine2, the EntityManager likes to close in a manner that makes it impossible to continue using said EntityManager. The prevailing thought seems to be that you should create a new EntityManager as opposed to being allowed to catch this simple exception and handle it in a graceful manner (wonderful design there guys /sarcasm).

However a problem arises when using the Bisna library/ZF 1.12 with a closed entity manager. The Bisna library doesn't provide for a public method to create a new EntityManager with the same name (i.e. "default") after it's been closed in the Container class.

My question is what is the best way to deal with this issue. There simply has to be a way to recover gracefully after an integrity constraint violation.

like image 983
VTEX Avatar asked Sep 05 '12 05:09

VTEX


1 Answers

In stead of trying to recover from these situations, you should focus on preventing integrity constraint violations:

  • If you hit a foreign key constraint, you're not tying the entities together in the right manner.
  • If you hit a unique constraint, you should check the db for possible duplicate data before trying to persist it.
  • If you hit another type of constraint and don't know how to prevent it, please ask :)

UPDATE:

The reason Doctrine2 closes the EntityManager is because in most cases it's no longer safe to use. Its UnitOfWork contains operations that cannot be done (hence the exception that's thrown).

You are correct that the Bisna library doesn't support creating a new EntityManager. You can extend it in order to implement such functionality yourself.

Another solution would be to handle transactions manually:

$em->getConnection()->beginTransaction(); // suspend auto-commit
try {
    // do some work
    $user = new User;
    $user->setName('George');
    $em->persist($user);
    $em->flush();
    $em->getConnection()->commit();
} catch (Exception $e) {
    $em->getConnection()->rollback();
    $em->clear();  // in stead of $em->close();
    throw $e;
}

By replacing $em->close() with $em->clear() you keep the EntityManager open and clean to use again.

I highly encourage you to either close or clear the EntityManager, as the data in it is (almost always) no longer usable.

like image 196
Jasper N. Brouwer Avatar answered Oct 23 '22 19:10

Jasper N. Brouwer