Three entities and integrity constraint - symfony

I have three entities:
School
Schooltype
Branch
With following relation:
Schooltype to School (One to Many)
Schooltype to Branch (One to Many)
Branch to School (One to Many)
If i update my database structure "php app/console doctrine:schema:update --force" i receive following error message.
[Doctrine\DBAL\DBALException]
An exception occurred while executing 'ALTER TABLE school ADD CONSTRAINT FK_F99EDABBDCD6CC49 FOREIGN KEY (branch_id) REFERENCES schooltype_branch (id)':
SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`ebm2`.`#sql-3cf_e6e`, CONSTRAINT `FK_F99EDABBDCD6CC49` FOREIGN KEY (`branch_id`) REFERENCES `schooltype_branch`
(`id`))
But i do not find my mistake, can somebody give me a hint for this issue?
I will also show some relevant parts of my three entities:
School:
class School implements BuildingInterface
{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\ManyToOne(targetEntity="SchoolType", inversedBy="schools")
* #ORM\JoinColumn(name="schooltype_id", referencedColumnName="id")
*/
protected $schooltype;
/**
* #ORM\ManyToOne(targetEntity="SchooltypeBranch", inversedBy="school")
* #ORM\JoinColumn(name="branch_id", referencedColumnName="id")
*/
protected $branch;
}
Schooltype:
class SchoolType implements BuildingTypeInterface
{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\OneToMany(targetEntity="Ebm\UserBundle\Entity\School", mappedBy="schooltype")
*/
protected $schools;
/**
* #ORM\OneToMany(targetEntity="Ebm\UserBundle\Entity\SchooltypeBranch", mappedBy="schooltype")
*/
protected $branch;
}
Schooltype Branch:
class SchooltypeBranch
{
/**
* #ORM\Column(type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\ManyToOne(targetEntity="SchoolType", inversedBy="branch")
* #ORM\JoinColumn(name="schooltype_id", referencedColumnName="id")
*/
protected $schooltype;
/**
* #ORM\OneToMany(targetEntity="Ebm\UserBundle\Entity\School", mappedBy="branch")
*/
protected $school;
}

Apparently a foreign key constraint is failing, like if school table has a branch_id not present in schooltype_branch table.

Related

Foreign key and cascade problems on delete Symfony4

An entity project can have many personnages, many chapitres, one highConcept for each project. And the user can have many projects. Then, when I want to remove a project I have this error message :
An exception occurred while executing 'DELETE FROM projets WHERE id = ?' with params [2]:
SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or update a parent row: a foreign key constraint fails (writtle.personnages, CONSTRAINT FK_286738A6C18272 FOREIGN KEY (projet_id) REFERENCES projets (id))
this is my entities:
Personnages Entity
/**
* #ORM\ManyToMany(targetEntity="App\Entity\Chapitre", mappedBy="personnages")
* #ORM\JoinColumn(name="projet_id", referencedColumnName="id", onDelete="CASCADE")
*/
private $chapitres;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Projets", inversedBy="personnages")
* #ORM\JoinColumn(name="projet_id", referencedColumnName="id", onDelete="CASCADE")
*/
private $projet;
Projet entity
/**
* #ORM\ManyToOne(targetEntity="App\Entity\User", inversedBy="projets")
* #ORM\JoinColumn(name="user_id", referencedColumnName="id")
*/
private $user;
/**
* #ORM\OneToMany(targetEntity="App\Entity\Personnages", mappedBy="projet")
*/
private $personnages;
/**
* #ORM\OneToMany(targetEntity="App\Entity\Chapitre", mappedBy="projet", cascade={"remove"})
* #ORM\joinColumn(onDelete="SET NULL")
*/
private $chapitres;
Chapitre entity
/**
* #ORM\ManyToOne(targetEntity="App\Entity\Projets", inversedBy="chapitres")
*/
private $projet;
/**
* #ORM\ManyToMany(targetEntity="App\Entity\Personnages", inversedBy="chapitres")
*/
private $personnages;
HighConcept
/**
* #ORM\OneToOne(targetEntity="App\Entity\Projets", cascade={"persist", "remove"})
*/
private $projet;
/**
* #ORM\ManyToOne(targetEntity="App\Entity\User", inversedBy="highconcepts")
*/
private $user;
User entity
/**
* #ORM\OneToMany(targetEntity="App\Entity\Projets", mappedBy="user")
*/
private $projets;
/**
* #ORM\OneToMany(targetEntity="App\Entity\Highconcept", mappedBy="user")
*/
private $highconcepts;
I don't know how I can relate this, I tried some things like JoinColumn ondelete cascade...
I see some topics, but I think I use it correctly.
Considering that you want to remove all the entities contained in your project I suggest you to use the orphanRemoval option as explained in the Doc.
There is another concept of cascading that is relevant only when removing entities from collections. If an Entity of type A contains references to privately owned Entities B then if the reference from A to B is removed the entity B should also be removed, because it is not used anymore.
making the members of your entity look like:
/**
* #ORM\OneToMany(targetEntity="App\Entity\Personnages", mappedBy="projet", orphanRemoval=true)
*/
private $personnages;

Symfony3 - Delete Entity with OneToMany - relationship in Doctrine - cascade not working

I have two entities:
/**
* Course
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="AppBundle\Entity\Repository\CourseRepository")
*/
class Course
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var \Doctrine\Common\Collections\ArrayCollection()
*
* #ORM\OneToMany(targetEntity="AppBundle\Entity\TimeTableEntry", mappedBy="course", cascade={"remove"}, orphanRemoval=true)
*
*/
private $timeTableEntries;
/**
* #var boolean
*
* #ORM\Column(name="enabled", type="boolean", nullable=true)
*/
private $enabled;
and
/**
* TimeTableEntry
*
* #ORM\Table()
* #ORM\Entity(repositoryClass="AppBundle\Entity\Repository\TimeTableEntryRepository")
*/
class TimeTableEntry
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var \Doctrine\Common\Collections\ArrayCollection()
*
* #ORM\ManyToOne(targetEntity="AppBundle\Entity\Course", inversedBy="timeTableEntries", cascade={"ALL"})
* #ORM\JoinColumn(name="course_id", referencedColumnName="id", nullable=true, onDelete="CASCADE")
*/
private $course;
As you can see I tried with cascade={"ALL"}, onDelete="CASCADE" and orphanRemoval=true.
When I want to delete the Course Entity I get the error message:
SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or
update a parent row: a foreign key constraint fails
(edutalk.teaching_event, CONSTRAINT FK_F2B1088B57042871 FOREIGN
KEY (time_table_entry_id) REFERENCES time_table_entry (id))
What can I try to resolve this?
I cannot comment on your post, so I post it as an answer.
Your problem is that you have another entity TeachingEvent with a reference to TimeTableEntry. When you try to delete a TimeTableEntry, it is impossible because this time_table_entry_id is still referenced as a foreign key in the TeachingEvent table.
Before deleting the TimeTableEntry, first you should unlink it from the TeachingEvent. I don't have your code, but depending on how TimeTableEntry and TeachingEvent relate to each other, it's probably something like:
$teachingEvent->setTimeTableEntry(null);
or
$timeTableEntry->setTeachingEvent(null);

Removing related entity Symfony2

I have related entities. Many to Many relation and the annotation exists on only one entity:
/**
* #ORM\ManyToMany(targetEntity="Event")
* #ORM\JoinTable(name="viewed_events",
* joinColumns={#ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={#ORM\JoinColumn(name="event_id", referencedColumnName="id")}
* )
**/
protected $viewedEvents;
The problem is when I try to delete Event entity I get Integrity constraint violation: 1451 Cannot delete or update a parent row: a foreign key constraint fails error. How do I solve this? I tried adding orphanRemoval=true like that: #ORM\ManyToMany(targetEntity="Event", orphanRemoval=true) and also tried adding cascade="delete" and cascade="all" instead with no success.
I give you one simple example so that you can work out what you need to add/change in your application.
Assume that there is a M-N relationship between Student and Course entities.
STUDENT
class Student
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\OneToMany(targetEntity="StudentCourse", mappedBy="studentInverse", cascade={"persist", "remove"})
*/
protected $studentInverse;
public function __construct()
{
$this->studentInverse = new \Doctrine\Common\Collections\ArrayCollection();
}
}
COURSE
class Course
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\OneToMany(targetEntity="StudentCourse", mappedBy="courseMap", cascade={"persist", "remove"})
*/
protected $courseInverse;
public function __construct()
{
$this->courseInverse = new \Doctrine\Common\Collections\ArrayCollection();
}
}
STUDENTCOURSE (this the one you're more interested in)
class StudentCourse
{
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\ManyToOne(targetEntity="Course", inversedBy="courseInverse")
* #ORM\JoinColumn(name="course", referencedColumnName="id", nullable=false, onDelete="CASCADE")
*/
protected $courseMap;
/**
* #ORM\ManyToOne(targetEntity="Student", inversedBy="studentInverse")
* #ORM\JoinColumn(name="student", referencedColumnName="id", nullable=false, onDelete="CASCADE")
*/
protected $studentMap;
}
onDelete="CASCADE"
On Yours JoinColumn.

Symfony + Doctrine - UnitOfWork commit order

I have a form that shows entity:
class Event
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
*
* #ORM\OneToMany(targetEntity="EventAttendee", mappedBy="event", cascade={"all"})
*/
private $attendees;
}
and a collection within it:
class EventAttendee
{
/**
* #var integer
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
*
* #ORM\ManyToOne(targetEntity="Event", inversedBy="attendees")
* #ORM\JoinColumn(name="event_id", referencedColumnName="id", onDelete="CASCADE")
*/
private $event;
/**
*
* #ORM\OneToOne(targetEntity="Employee")
* #ORM\JoinColumn(name="employee_id", referencedColumnName="id", onDelete="CASCADE")
*/
private $employee;
}
If I delete an employee from the collection and add it again, I'm getting integrity constraint violation. This is because Doctrine's UnitOfWork first executes Inserts and then Deletes. Therefore, when it inserts a new record db still has the old one with the same employee.
Doctrine2 developers did not provide any working solution for Symfony2 users (here is the thread: http://www.doctrine-project.org/jira/browse/DDC-601).
And thus, I'm asking the question here: is it anyhow possible to avoid this issue?
EDIT:
My current workaround is:
find all not-persisted colletion items ready to insert
remove them from the collection and save to a variable
remove all the items that were really deleted in the form
call flush()
add all the items for insert back to the collection
call flush()
This works for me, however doesn't look good. Maybe someone has a better solution.

How do I generate ID when I have composite keys in Doctrine?

I have a Entity with composite keys. See below:
class BankAccount {
/**
* #ORM\Id
* #ORM\Column(type="integer")
*
*/
protected $bank;
/**
* #ORM\Id
* #ORM\ManyToOne(targetEntity="CompanyBundle\Entity\Company")
*/
protected $company;
...
}
because Doctrine has some issues with composite keys it won't generates sequences (I'm working in PostgreSQL), how do I deal with this in order to generate $bank which is the PK?
If sounds like you don't want a composite key, just a primary key on $bank and a foreign key on $company. If that's the case,
class BankAccount {
/**
* #ORM\Id
* #ORM\Column(type="integer")
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $bank;
/**
* #ORM\ManyToOne(targetEntity="CompanyBundle\Entity\Company")
*/
protected $company;
...
}
should do it.

Resources