Упрощенно, у меня есть эта таблица:
tree_table
--------------------
id|root_id|parent_id
1 |null |null
2 |1 |1
3 |2 |1
Для этого у меня есть эта сущность:
namespace StackOverflow;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Table(name="tree_table")
*/
class TreeTable {
/**
* @ORM\Column(name="id", type="bigint", nullable=false)
* @ORM\Id
*/
public id;
/**
* @ORM\OneToOne(targetEntity="StackOverflow\TreeTable")
* @ORM\JoinColumn(name="root_id", referencedColumnName="id")
*/
public root;
/**
* @ORM\OneToOne(targetEntity="StackOverflow\TreeTable")
* @ORM\JoinColumn(name="parent_id", referencedColumnName="id")
*/
public parent;
}
Я пытаюсь скопировать дерево из этой таблицы. Я могу легко выбрать все дерево, сказав WHERE root_id = :rootId OR id = :rootId
. Но при копировании я должен изменить родительские идентификаторы.
Я вижу каноническое решение, в котором я просто говорю что-то вроде этого:
foreach ($trees as $treePart) {
$newTreePart = new TreeTable();
$this->copyNeededThings($treePart, $newTreePart); // copies information that I want to have copied
/**
* Find the corresponding new parent and add it to this newTreePart by calling
* $newTreepart->parent = $thatNewParent
*/
$this->addToParent($treePart, $newTreePart);
}
Но, делая это таким образом, я должен сохраняйте все дерево в памяти, и я боюсь, что мне быстро не хватит памяти. Я бы предпочел сделать два разбора по дереву. В первом разборе я создам все новые деревья, но оставлю родителей такими, какими они были изначально. И я создам карту, сопоставляя оригинальные идентификаторы сущностей с новыми идентификаторами. Во второй части я буду использовать карту, чтобы установить идентификаторы. Это позволило бы разбить эту процедуру на страницы.
Но я не знаю, как установить внешний ключ через ключ напрямую через doctrine. Создать второй файл сущности для той же таблицы? Должен ли я добавить столбцы непосредственно к этой сущности и иметь отношение и столбец в одной таблице. Я думаю, что я мог бы также просто создать сущности TreeTable в качестве контейнера данных для идентификатора, но я беспокоюсь, что в будущем кто-то может добавить каскадное сохранение, а затем это будет неправильно понято как обновления базы данных.
Есть ли хороший, чистое решение для этой проблемы?