2013-12-10 2 views
0

У меня есть следующая проблема, и я не вижу никакого решения (даже менее вероятно после анализа исходного кода доктрины). Проблема заключается в следующем:Доктрина Многие из многих недостатков

У меня есть два класса сущности, скажем, Автор и Книга. Мое предположение состоит в том, что одна книга может быть написана многими авторами, так что это будет отношение «многие ко многим» к Автору в качестве владельца. Теперь я хочу иметь одно действие, в котором я могу создать новую книгу и сразу назначить ее существующему автору, и я знаю идентификатор автора, поэтому не требуется фактически выбирать автора из базы данных. И поэтому я могу попытаться:

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

В чем проблема с вышеуказанным кодом? Предположим, что отношение имеет cascade = "persist". Если кто-то из вас попытается это сделать, вы получите действительно странный результат: книга будет добавлена ​​в базу данных, но отношение не будет сохранено, потому что частичная ссылка отмечена как readOnly в доктрине UnitOfWork и из-за этой доктрины не будет сохранить любые изменения, сделанные на нем, но по какой-то причине он будет следовать за каскадным сопротивлением.

Таким образом, мы можем попробовать другой подход:

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

Это один работает, но она будет выбирать все данные автора в строке, что я уже комментировал, как «проблематично», потому что прокси-класс при условии, доктрина в качестве ссылки будет lazy-load все атрибуты при любом вызове метода, выполняемом автором, с одним исключением и getId(), который, очевидно, бесполезен в этой ситуации.

Так что мой вопрос: Я не прав? Я что-то пропустил?

ответ

0

Нет. Вы ничего не пропустили. Второй образец правильный. :)

Я верю, что вы видите, когда вы очищаете транзакцию обновления, она по-прежнему сначала выполняет оператор выбора для получения связанной записи. С точки зрения SQL это неэффективно, но способ Doctrine работает.

+0

Да, вы правы, это именно то, что я имел в виду, и почти точно, что я вижу. Если быть точным - доктрина выполняет совершенно ненужный выбор в ответ на вызов addBook() (а не флеш), чтобы предоставлять данные в случае, если addBook() возвращает любые данные из объекта. Есть ли способ сделать это правильно, не выполняя выбор (конечно, я все еще хочу, чтобы автор был стороной, владеющей отношениями, я прекрасно понимаю, что это будет работать наоборот)? – Mikz

+0

Единственный способ, которым я знаю, - перейти на низкоуровневый и использовать собственный SQL-запрос. Подробнее см. В [этот пост] (http://stackoverflow.com/questions/3325012/execute-raw-sql-using-doctrine-2). Еще одна вещь, которую следует учитывать: насколько важна производительность в этом случае? Стоит ли отойти от рамочных соглашений, чтобы сэкономить время на несколько миллисекунд? (Это не риторический, но что-то стоит подумать.) – Rob

+0

Большое спасибо за ваши ответы. В этом случае производительность не так важна, потому что я создаю небольшую внутреннюю систему компании для управления данными. Он будет использоваться менее чем 20 людьми (отдел SEO и контент-провайдеры), и он не будет содержать много данных. Однако мне просто интересно, как все работает, и я всегда стараюсь делать все как можно эффективнее - пока это не потребует больше усилий, чем того стоит. В этом конкретном случае это не стоит :). – Mikz

Смежные вопросы