在 Doctrine2 实体中了解 "transitive persistence / cascade operations"

Understanding "transitive persistence / cascade operations" at Doctrine2 entities

我将开始 post 说我已经阅读了 docs 但相反的帮助我在这一点上更加困惑。

让我们用 ManyToOneManyToMany 关系获取一些实体(实际用例是我项目的一部分)。

// This is the main entrance point
class SolicitudUsuario
{

}

// Each SolicitudUsuario can have one|many ProductoSolicitud
class ProductoSolicitud
{
    /**
     * @var \SolicitudUsuario
     *
     * @ORM\ManyToOne(targetEntity="SolicitudUsuario", cascade={"persist"})
     * @ORM\JoinColumn(name="solicitud_usuario_id", referencedColumnName="id")
     */
    protected $solicitud_usuario;

    /**
     * @ORM\ManyToMany(targetEntity="CodigoArancelario", inversedBy="codigoArancelarioProducto", cascade={"persist"})
     * @ORM\JoinTable(name="negocio.producto_codigo_arancelario", schema="negocio",
     *      joinColumns={@ORM\JoinColumn(name="producto_solicitud_id", referencedColumnName="id")},
     *      inverseJoinColumns={@ORM\JoinColumn(name="codigo_arancelario_id", referencedColumnName="id")}
     * )
     */
    protected $productoCodigosArancelarios;
}


// Each ProductoSolicitud can have one|many MarcaProductoSolicitud
// Each ProductoSolicitud can have one|many ModeloProductoSolicitud
// Each ProductoSolicitud can have one|many FabricanteProductoSolicitud

class ModeloMarcaProducto
{
    /**
     * @ORM\ManyToOne(targetEntity="MarcaProductoSolicitud")
     * @ORM\JoinColumn(name="marca_producto_id", referencedColumnName="id")
     */
    protected $marca_producto;

    /**
     * @ORM\ManyToOne(targetEntity="ModeloProductoSolicitud")
     * @ORM\JoinColumn(name="modelo_producto_id", referencedColumnName="id")
     */
    protected $modelo_producto;

    /**
     * @ORM\ManyToOne(targetEntity="ProductoSolicitud")
     * @ORM\JoinColumn(name="producto_solicitud_id", referencedColumnName="id")
     */
    protected $producto_solicitud;

    /**
     * @ORM\ManyToMany(targetEntity="FabricanteProductoSolicitud", mappedBy="fabricanteModeloMarcaProducto", cascade={"persist"})
     */
    protected $modeloMarcaProducto;
}

// Each FabricanteProductoSolicitud can have one|many FabricanteDistribuidor
// Each ProductoSolicitud can have one|many Pais

class FabricanteProductoSolicitud
{
    /**
     * @ORM\ManyToOne(targetEntity="FabricanteDistribuidor")
     * @ORM\JoinColumn(name="fabricante_distribuidor_id", referencedColumnName="id")
     */
    protected $fabricante_distribuidor;

    /**
     * @ORM\ManyToOne(targetEntity="ProductoSolicitud")
     * @ORM\JoinColumn(name="producto_solicitud_id", referencedColumnName="id")
     */
    protected $producto_solicitud;

    /**
     * @ORM\ManyToMany(targetEntity="Pais", inversedBy="fabricanteProductoSolicitudPais", cascade={"persist"})
     * @ORM\JoinTable(name="nomencladores.pais_fabricante_producto_solicitud", schema="nomencladores",
     *      joinColumns={@ORM\JoinColumn(name="fabricante_producto_solicitud_id", referencedColumnName="id")},
     *      inverseJoinColumns={@ORM\JoinColumn(name="pais_id", referencedColumnName="id")}
     * )
     */
    protected $paisesFabricanteProductoSolicitudPais;

    /**
     * @ORM\ManyToMany(targetEntity="ModeloMarcaProducto", inversedBy="modeloMarcaProducto", cascade={"persist"})
     * @ORM\JoinTable(name="negocio.fabricante_modelo_marca_producto", schema="negocio",
     *      joinColumns={@ORM\JoinColumn(name="fabricante_producto_solicitud_id", referencedColumnName="id")},
     *      inverseJoinColumns={@ORM\JoinColumn(name="modelo_marca_producto_id", referencedColumnName="id")}
     * )
     */
    protected $fabricanteModeloMarcaProducto;
}

现在,我想删除一个SolicitudUsuario。拥有如上所示的实体,我需要手动处理每个依赖实体吗?正确的?这是一种疯狂的原因,可以管理很少的实体,但管理大量实体将是一件痛苦的事情!

我的问题是如果我将 cascade={"persist", "remove"} 添加到 ManyToOneManyToMany 关系会发生什么?如果我删除第一个 SolicitudUsuario 是否应该删除其余的级联?

任何人都可以指出正确的方向并给我一个很好的解释吗?

为避免循环,您可以使用数据库级别cascade delete。将映射更改为:

/**
 * @ORM\ManyToOne(targetEntity="ProductoSolicitud")
 * @ORM\JoinColumn(name="producto_solicitud_id", referencedColumnName="id", onDelete="CASCADE")
 */
protected $producto_solicitud;

或使用DQL bulk delete,如

    $q = $em->createQuery("delete from Name\Space\FacturaProductoSolicitud f where f.producto_solicitud= some_id")
            ->execute();

还有其他选择,但我认为这两个是最有效的。