ReynierPM
ReynierPM

Reputation: 18680

Understanding "transitive persistence / cascade operations" at Doctrine2 entities

I'll start the post saying that I read already the docs but opposite to help I'm more confused at this point.

Lets take a some entities (real use case is part of my project) with ManyToOne and ManyToMany relationships.

// 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;
}

Now, I want to delete a SolicitudUsuario. Having the entities as show above I need to take care manually on each dependent entity? Right? This is kind of crazy cause with few entities can be managed but with a large set of entities will be a pain!

My question what should happen if I add cascade={"persist", "remove"} to ManyToOne & ManyToMany relations? If I remove the first SolicitudUsuario should be removed the rest on cascade?

Can any point me on the right direction and give me a good explanation?

Upvotes: 1

Views: 235

Answers (1)

qtuan
qtuan

Reputation: 687

To avoid the loop, you can use database level cascade delete. Change your mapping as:

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

Or use DQL bulk delete, such as

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

There are other options as well but I think these 2 are the most efficient.

Upvotes: 1

Related Questions