Developer
Developer

Reputation: 2895

persist Integrity constraint oneToOne

Entities :

Entity Miejsce

class Miejsce
{

  /**
 *
 * @var Lokalizacja $lokalizacja
 * @ORM\OneToOne(targetEntity="Miejsce\LokalizacjaBundle\Entity\Lokalizacja",cascade={"persist"})
 * @ORM\JoinColumn(name="id", referencedColumnName="miejsce_id")
 */
protected $lokalizacja;

Entity Lokalizacja

class Lokalizacja {

    /**
     * Lokalizacja.id = Miejsce.id
     * @ORM\Column(type="integer")
     * @ORM\Id
     */
    protected $id;


       /**
 * @var Miejsce
 * @ORM\OneToOne(targetEntity="Miejsce\ObiektyBundle\Entity\Miejsce", inversedBy="lokalizacja")
 * @ORM\JoinColumn(name="miejsce_id", referencedColumnName="id")
 */
protected $miejsce;

    /**
     * @ORM\Column(type="integer")
     */
    protected $miejsce_id;

i Create new Miejsce

$miejsce = new Miejsce();

.... $em->persist($miejsce); $em->flush();

and get

SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`symfony2_KPB_lazy`.`mMiejsce`, CONSTRAINT `FK_41DB4C8BF396750` FOREIGN KEY (`id`) REFERENCES `mLokalizacja` (`miejsce_id`)) 

if i first setup lokalizacja

 $lokalizacja = new Lokalizacja();
        $lokalizacja->setLat($a['lat']);
        $lokalizacja->setLng($a['lng']);
        $em->persist($lokalizacja);
        $em->flush();

SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'miejsce_id' cannot be null

if i add persist

 /**
     *
     * @ORM\OneToOne(targetEntity="Miejsce\LokalizacjaBundle\Entity\Lokalizacja",cascade={"persist"})
     * @ORM\JoinColumn(name="id", referencedColumnName="miejsce_id")
     */
    protected $lokalizacja;

An exception occurred while executing 'INSERT INTO mLokalizacja (miejsce_id, lat, lng, zoom, textAdres, mMiejscowosci_id, mPowiaty_id, mWojewodztwa_id, street) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)' with params [null, 49.658192, 18.825332, null, null, null, null, null, null]:

SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'miejsce_id' cannot be null

when run code

    $miejsce = new Miejsce();

        $lokalizacja = new Lokalizacja();
        $lokalizacja->setLat($a['lat']);
        $lokalizacja->setLng($a['lng']);
        $lokalizacja->setMiejsce($miejsce);

        $miejsce->setLokalizacja($lokalizacja);

 $em->persist($miejsce);
        $em->flush();

when i try add miejsce in phpMyAdmin - i get

1452 - Cannot add or update a child row: a foreign key constraint fails (symfony2_KPB.mMiejsce, CONSTRAINT FK_41DB4C8BF396750 FOREIGN KEY (id) REFERENCES mLokalizacja (miejsce_id))

So how to add Miejsce ?

UPDATE1

class Miejsce
{

    /**
     * @var Lokalizacja $lokalizacja
     * @ORM\OneToOne(targetEntity="Miejsce\LokalizacjaBundle\Entity\Lokalizacja")
     */
    protected $lokalizacja;



/**
 * @ORM\Entity
 *
 * @ORM\Table(name="mLokalizacja", indexes={
    @ORM\Index(name="index_latLng", columns={"lat","lng"})
})
*
 */
class Lokalizacja {

    /**
     * @var Miejsce
     * @ORM\OneToOne(targetEntity="Miejsce\ObiektyBundle\Entity\Miejsce", inversedBy="lokalizacja")
     * @ORM\JoinColumn(name="miejsce_id", referencedColumnName="id")
     */
    protected $miejsce;

i update database and see (this is phpmyadmin table structure):

CREATE TABLE IF NOT EXISTS `mMiejsce` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `nazwa` varchar(255) COLLATE utf8_polish_ci NOT NULL,
  `parent_id` int(11) DEFAULT NULL,
  `lokalizacja_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),

and lokalizacja 
CREATE TABLE IF NOT EXISTS `mLokalizacja` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `lat` double NOT NULL,
  `lng` double NOT NULL,
  `zoom` int(11) NOT NULL,
  `miejsce_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `UNIQ_4FC27791464204DC` (`miejsce_id`),

Why doctrine add lokalizacja_id to mMiejsce ? And still save is not possible

UPDATE2 i add mappedBy="miejsce", database look ok now but when i try save

class Miejsce
{
    /**
     * @var Lokalizacja $lokalizacja
     * @ORM\OneToOne(targetEntity="Miejsce\LokalizacjaBundle\Entity\Lokalizacja" , mappedBy="miejsce")
     */
    protected $lokalizacja;

have error :

A new entity was found through the relationship 'Miejsce\ObiektyBundle\Entity\Miejsce#lokalizacja' that was not configured to cascade persist operations for entity: Miejsce\LokalizacjaBundle\Entity\Lokalizacja@000000006200f93900007f919f6a5a6f. To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity or configure cascade persist this association in the mapping for example @ManyToOne(..,cascade={"persist"}). If you cannot find out which entity causes the problem implement 'Miejsce\LokalizacjaBundle\Entity\Lokalizacja#__toString()' to get a clue.

so i add ,cascade={"persist"}

 * @ORM\OneToOne(targetEntity="Miejsce\LokalizacjaBundle\Entity\Lokalizacja" , mappedBy="miejsce" ,cascade={"persist"})

now entity save succes but :) i cant delete it - when i try delete miejsce -

i found onDelete="CASCADE" - but have error :

Creation Error] The annotation @ORM\OneToOne declared on property Miejsce\ObiektyBundle\Entity\Miejsce::$lokalizacja does not have a property named "onDelete". Available properties: targetEntity, mapped  
  By, inversedBy, cascade, fetch, orphanRemoval                                                                                                            

when add to * @ORM\OneToOne(targetEntity="Miejsce\LokalizacjaBundle\Entity\Lokalizacja" , mappedBy="miejsce" ,cascade={"persist"})

So where add cascade delete ?

UPDATE3

ok when i add

 * @ORM\JoinColumn(name="miejsce_id", referencedColumnName="id", onDelete="CASCADE")

to lokalizacja everythink work.

Upvotes: 0

Views: 1170

Answers (1)

Jivan
Jivan

Reputation: 23068

You are trying to establish a oneToOne bidirectional relationship. Such a relationship (as all bidirectional ones) needs the mention inversedBy on one side and mappedBy on the other, which you forgot in your annotation.

For more detailed informations about relationships, see Doctrine documentation.

But regarding your particular need, you can start with the following.

Miejsce:

class Miejsce
{
    /**
     * @OneToOne(targetEntity="Lokalizacja", mappedBy="miejsce", cascade={"remove"})
     */
    private $lokalizacja;

Here is where you forgot mappedBy.

Lokalizacja:

class Lokalizacja
{
    /**
     * @OneToOne(targetEntity="Miejsce", inversedBy="lokalizacja")
     */
    private $miejsce;

When you join based on the id, JoinColumn is optional and you can omit it (as I did).

Then, you go on normally with:

// (...)
$em->persist($miejsce);
$em->flush();

Upvotes: 1

Related Questions