0

I've got following problem and I can't see any solution (even less probable after analysing doctrine source code). The problem is following:

I've got two entity classes, let's say Author and Book. My assumption is that one book can be written by many authors, so it will be many-to-many relation with Author as an owner. Now I want to have one action where I can create new book and immediately assign it to existing author and I know id of an author so it shouldn't be required to actually select the author from database. And so I can try to:

$book = new Book();
//assign data to book
$author = $em->getPartialReference('Author', $idOfAuthor);
$author->addBook($book);
$em->persist($author);
$em->flush();

What's the problem with the above code? Let's say that relation has cascade="persist". If anyone of you would try to do that, you'll get really odd result: book will be added to database, but relation won't be saved because partial reference is marked as readOnly in doctrine UnitOfWork and because of that doctrine won't save any of modifications made on it but for some reason it WILL follow cascade persistance.

So we can try different approach:

$book = new Book();
//assign data to book
$author = $em->getReference('Author', $idOfAuthor);
$author->addBook($book); //here's problematic line
$em->persist($author);
$em->flush();

That one works but it will select all data of an author at line that i've commented as 'problematic' because proxy class provided by doctrine as reference will lazy-load all attributes on any method call performed on author with just one exception ant it's getId() which is obviously useless in that situation.

So my question is: Am I wrong? Did I miss something?

Mikz
  • 660
  • 6
  • 14

1 Answers1

0

No. You didn't miss anything. The second sample is correct. :)

I believe what you're seeing is when you flush the update transaction it still first executes a select statement to retrieve the related record. From a SQL standpoint, this is inefficient, but the way Doctrine works.

Rob
  • 506
  • 4
  • 9
  • Yes, you're right, that's exactly what I meant and almost exactly what I'm seeing. To be precise - doctrine performs totally unnecessary select in reaction to addBook() call (not flush) in order to provide data in case of addBook() returns any data from entity. Is there any way to do this right without performing select (of course I still want the Author to be the owning side of relation, I'm perfectly aware that it will work in opposite way)? – Mikz Dec 10 '13 at 20:29
  • The only way I know is to go low-level, and use a native SQL query. See [this post](http://stackoverflow.com/questions/3325012/execute-raw-sql-using-doctrine-2) for details. One additional thing to consider: how important is performance in this case? Is it worth moving away from framework conventions to shave a few milliseconds off execution time? (This is not rhetorical, but something worth thinking about.) – Rob Dec 10 '13 at 21:16
  • Thank you very much for your answers. In that case the performance is not so important because I'm creating small internal company system for data management. It will be used by less than 20 people (SEO department and content providers) and it won't contain much data. However I'm just curious about how things work and I'm always trying to do things as efficient as possible - as long as it won't require more effort than it is worth. In that specific case it's not worth it :). – Mikz Dec 10 '13 at 21:30