理解Doctrine2实体中的“传递持久性/级联操作”

时间:2015-02-03 16:22:30

标签: php symfony doctrine-orm doctrine

我会开始发帖说我已经阅读了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"}添加到ManyToOne& ManyToMany关系?如果我删除第一个SolicitudUsuario应该删除其余的级联?

我能指出正确的方向并给我一个很好的解释吗?

1 个答案:

答案 0 :(得分:1)

要避免循环,可以使用数据库级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();

还有其他选择,但我认为这两种选择效率最高。