我有以下两个实体:
/** @Entity @Table(name="invoice") */
class Invoice {
/** @Id @Column(type="integer") @GeneratedValue */
protected $id;
...
/** @OneToMany(targetEntity="InvoiceRow", mappedBy="invoice", fetch="EAGER", cascade={"persist", "remove"}, orphanRemoval=true) */
protected $rows = null;
...
public function __construct() {
$this->rows = new ArrayCollection();
}
...
public function getRows() {
return $this->rows;
}
public function addRow($row) {
$this->rows[] = $row;
$row->setInvoice($this);
}
public function emptyRows() {
$this->rows = new ArrayCollection();
}
}
/** @Entity @Table(name="invoice_row") */
class InvoiceRow {
/** @Id @Column(type="integer") @GeneratedValue */
protected $id;
...
/** @ManyToOne(targetEntity="Invoice", inversedBy="rows") */
protected $invoice;
...
public function getInvoice() {
return $this->invoice;
}
public function setInvoice($invoice) {
$this->invoice = $invoice;
}
}
因此,一个Invoice
的示例可以关联许多InvoiceRow
的示例。在DB上反映实体结构之后,我在表invoice_row
中有字段invoice_id
,它正确地引用了表invoice
的相关记录的id
。
由于可以添加、删除或修改发票的每一行,因此每次保存发票时,我都希望删除InvoiceRow
的所有关联记录,并在从前端接收到这些记录时重新创建这些记录。
这是代码:
public static function saveInvoice($invoiceData, $invoiceRows) {
$em = getEntityManager();
$dbInvoice = null;
if ($invoiceData->id) {
// if is an exsisting invoice, i get it from the DB, so Doctrine will execute an update instead of an insert
$dbInvoice = $em->find(Invoice::class, $invoiceData->id);
}
$dbInvoice->emptyRows(); // deleting all the rows from the entity Invoice
// adding all the rows, as they were received from the frontend
foreach ($invoiceRows as $invoiceRow) {
$dbInvoiceRow = self::getDbInvoiceRow($invoiceRow) // map frontend object into the Doctrine entity InvoiceRow
$dbInvoice->addRiga($dbInvoiceRow);
}
$em->persist($dbInvoice);
$em->flush();
}
问题是,最后,不是只有从前端接收的行,而是仍然有所有旧的行,因为没有删除任何行。
举例来说:invoice_row
表中的原始数据:
| id | invoice_id | code | description |
| -- | ---------- | ---- | ----------- |
| 1 | 12 | 010 | product 01 |
| 2 | 12 | 008 | product 02 |
从前端接收的行:
| code | description |
| ---- | ----------- |
| 010 | product 01 |
| 012 | product 03 |
invoice_row表的预期内容:
| id | invoice_id | code | description |
| -- | ---------- | ---- | ----------- |
| 1 | 12 | 010 | product 01 |
| 3 | 12 | 012 | product 03 |
坚持后的真实的内容
| id | invoice_id | code | description |
| -- | ---------- | ---- | ----------- |
| 1 | 12 | 010 | product 01 | -> old row
| 2 | 12 | 008 | product 02 | -> old row
| 3 | 12 | 010 | product 01 |
| 4 | 12 | 012 | product 03 |
我做错了什么?
提前感谢大家。
1条答案
按热度按时间olmpazwi1#
最后我发现了重点。我很失望我不能通过cascade remove或其他注解来实现这一点,但我不得不编写更多的代码。下面是我怎么想出来的:
Invoice
中我将发票保存程序更改如下:
最后,为了使它更容易,我唯一能弄清楚的方法是显式调用
removeElement
,但将其作为Invoice
类中的一个函数包含在内,使其与实体本身更加一致。我希望这对未来的读者有所帮助。