Commit order issue #4924

Closed
opened 2026-01-22 14:52:03 +01:00 by admin · 5 comments
Owner

Originally created by @kilhage on GitHub (Dec 8, 2015).

I have a very annoying issue regarding the commit order calculated by the UnitOfWork & CommitOrderCalculator components.

I have two entities, the important parts in this case looks like this:

/**
 * @ORM\Entity()
 */
class Hotel
{
    /**
     * @var HotelImage
     *
     * @ORM\ManyToOne(targetEntity="HotelImage", inversedBy="thumbnailHotels")
     * @ORM\JoinColumn(name="thumbnail_id", referencedColumnName="id", nullable=true, onDelete="SET NULL")
     */
    private $thumbnail;

    /**
     * @var ArrayCollection
     *
     * @ORM\OneToMany(targetEntity="HotelImage", mappedBy="hotel")
     */
    private $images;
}
/**
 * @ORM\Entity()
 */
class HotelImage
{
    /**
     * @var Hotel
     *
     * @Assert\NotBlank()
     * @ORM\ManyToOne(targetEntity="Hotel", inversedBy="images")
     * @ORM\JoinColumn(name="hotel_id", referencedColumnName="id", onDelete="CASCADE", nullable=false)
     */
    private $hotel;

    /**
     * @var ArrayCollection
     *
     * @ORM\OneToMany(targetEntity="Hotel", mappedBy="thumbnail")
     */
    private $thumbnailHotels;
}

The code snippet I have problem when looks like this:

$country = $countryRepo->findByName('Sweden');
$city = $cityRepo->findByCountryAndName($country, 'Stockholm');

$hotel = $hotelRepo->findByCityAndName($city, 'Radisson Blu Waterfront Stockholm');

$image = new HotelImage();
$image->setHotel($hotel);
$hotel->addImage($image);
$em->persist($image);

$hotel2 = new Hotel();
$hotel2->setCity($city);
$hotel2->setName('xxxxxxx');
$em->persist($hotel2);

$image = new HotelImage();
$image->setHotel($hotel2);
$hotel2->addImage($image);
$em->persist($image);

$em->flush();

Then the following exception will be thrown:

  [Doctrine\DBAL\Driver\PDOException]
  SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'hotel_id' cannot be null

When looking at the sql statements executed I see these in the logs:

[2015-12-08 21:13:57] doctrine.DEBUG: INSERT INTO hotel_images (file_name, mime_type, url, code, created, updated, supplier_id, hotel_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?) {"1":null,"2":null,"3":null,"4":null,"5":"2015-12-08 21:13:56","6":"2015-12-08 21:13:56","7":null,"8":628550}
[2015-12-08 21:13:57] doctrine.DEBUG: INSERT INTO hotel_images (file_name, mime_type, url, code, created, updated, supplier_id, hotel_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?) {"1":null,"2":null,"3":null,"4":null,"5":"2015-12-08 21:13:56","6":"2015-12-08 21:13:56","7":null,"8":null}

If I instead run the following snippet:

$country = $countryRepo->findByName('Sweden');
$city = $cityRepo->findByCountryAndName($country, 'Stockholm');

$hotel2 = new Hotel();
$hotel2->setCity($city);
$hotel2->setName('xxxxxxx');
$em->persist($hotel2);

$image = new HotelImage();
$image->setHotel($hotel2);
$hotel2->addImage($image);
$em->persist($image);

$em->flush();
[2015-12-08 21:18:00] doctrine.DEBUG: INSERT INTO hotels (type, latitude, longitude, rating, user_score, number_of_reviews, phone_number, fax, url, check_in_time, check_out_time, number_of_rooms, street, postal_code, certified, certification_rating, center_distance, name, created, updated, thumbnail_id, hotel_chain_id, address_id, coordinates_id, city_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) {"1":null,"2":null,"3":null,"4":null,"5":0,"6":0,"7":null,"8":null,"9":null,"10":null,"11":null,"12":null,"13":null,"14":null,"15":false,"16":null,"17":null,"18":"xxxxxxx","19":"2015-12-08 21:18:00","20":"2015-12-08 21:18:00","21":null,"22":null,"23":null,"24":null,"25":2535}
[2015-12-08 21:18:00] doctrine.DEBUG: INSERT INTO hotel_images (file_name, mime_type, url, code, created, updated, supplier_id, hotel_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?) {"1":null,"2":null,"3":null,"4":null,"5":"2015-12-08 21:18:00","6":"2015-12-08 21:18:00","7":null,"8":642815}

The error occurs becouse depending on what entity gets persisted first, the \Doctrine\ORM\UnitOfWork::getCommitOrder will build commit order differently because the two entities are dependent of each other, but since the thumbnail_id is nullable this should still work..

One solution to this would of course be a different approach to the thumbnails but I'd stil expect the above test cases not to throw errors and the commit order to be consistent.

Please suggest a way around this without adding extra flushes, or change the order I persist the objects. I have a number of use cases in the project where this is used where I need to persist the objects in the order as in the test cases and can't add flushes because of performance reasons.

Any help is appreciated, thanks.

Originally created by @kilhage on GitHub (Dec 8, 2015). I have a very annoying issue regarding the commit order calculated by the UnitOfWork & CommitOrderCalculator components. I have two entities, the important parts in this case looks like this: ``` php /** * @ORM\Entity() */ class Hotel { /** * @var HotelImage * * @ORM\ManyToOne(targetEntity="HotelImage", inversedBy="thumbnailHotels") * @ORM\JoinColumn(name="thumbnail_id", referencedColumnName="id", nullable=true, onDelete="SET NULL") */ private $thumbnail; /** * @var ArrayCollection * * @ORM\OneToMany(targetEntity="HotelImage", mappedBy="hotel") */ private $images; } ``` ``` php /** * @ORM\Entity() */ class HotelImage { /** * @var Hotel * * @Assert\NotBlank() * @ORM\ManyToOne(targetEntity="Hotel", inversedBy="images") * @ORM\JoinColumn(name="hotel_id", referencedColumnName="id", onDelete="CASCADE", nullable=false) */ private $hotel; /** * @var ArrayCollection * * @ORM\OneToMany(targetEntity="Hotel", mappedBy="thumbnail") */ private $thumbnailHotels; } ``` The code snippet I have problem when looks like this: ``` php $country = $countryRepo->findByName('Sweden'); $city = $cityRepo->findByCountryAndName($country, 'Stockholm'); $hotel = $hotelRepo->findByCityAndName($city, 'Radisson Blu Waterfront Stockholm'); $image = new HotelImage(); $image->setHotel($hotel); $hotel->addImage($image); $em->persist($image); $hotel2 = new Hotel(); $hotel2->setCity($city); $hotel2->setName('xxxxxxx'); $em->persist($hotel2); $image = new HotelImage(); $image->setHotel($hotel2); $hotel2->addImage($image); $em->persist($image); $em->flush(); ``` Then the following exception will be thrown: ``` [Doctrine\DBAL\Driver\PDOException] SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'hotel_id' cannot be null ``` When looking at the sql statements executed I see these in the logs: ``` [2015-12-08 21:13:57] doctrine.DEBUG: INSERT INTO hotel_images (file_name, mime_type, url, code, created, updated, supplier_id, hotel_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?) {"1":null,"2":null,"3":null,"4":null,"5":"2015-12-08 21:13:56","6":"2015-12-08 21:13:56","7":null,"8":628550} [2015-12-08 21:13:57] doctrine.DEBUG: INSERT INTO hotel_images (file_name, mime_type, url, code, created, updated, supplier_id, hotel_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?) {"1":null,"2":null,"3":null,"4":null,"5":"2015-12-08 21:13:56","6":"2015-12-08 21:13:56","7":null,"8":null} ``` If I instead run the following snippet: ``` php $country = $countryRepo->findByName('Sweden'); $city = $cityRepo->findByCountryAndName($country, 'Stockholm'); $hotel2 = new Hotel(); $hotel2->setCity($city); $hotel2->setName('xxxxxxx'); $em->persist($hotel2); $image = new HotelImage(); $image->setHotel($hotel2); $hotel2->addImage($image); $em->persist($image); $em->flush(); ``` ``` [2015-12-08 21:18:00] doctrine.DEBUG: INSERT INTO hotels (type, latitude, longitude, rating, user_score, number_of_reviews, phone_number, fax, url, check_in_time, check_out_time, number_of_rooms, street, postal_code, certified, certification_rating, center_distance, name, created, updated, thumbnail_id, hotel_chain_id, address_id, coordinates_id, city_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) {"1":null,"2":null,"3":null,"4":null,"5":0,"6":0,"7":null,"8":null,"9":null,"10":null,"11":null,"12":null,"13":null,"14":null,"15":false,"16":null,"17":null,"18":"xxxxxxx","19":"2015-12-08 21:18:00","20":"2015-12-08 21:18:00","21":null,"22":null,"23":null,"24":null,"25":2535} [2015-12-08 21:18:00] doctrine.DEBUG: INSERT INTO hotel_images (file_name, mime_type, url, code, created, updated, supplier_id, hotel_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?) {"1":null,"2":null,"3":null,"4":null,"5":"2015-12-08 21:18:00","6":"2015-12-08 21:18:00","7":null,"8":642815} ``` The error occurs becouse depending on what entity gets persisted first, the \Doctrine\ORM\UnitOfWork::getCommitOrder will build commit order differently because the two entities are dependent of each other, but since the thumbnail_id is nullable this should still work.. One solution to this would of course be a different approach to the thumbnails but I'd stil expect the above test cases not to throw errors and the commit order to be consistent. Please suggest a way around this without adding extra flushes, or change the order I persist the objects. I have a number of use cases in the project where this is used where I need to persist the objects in the order as in the test cases and can't add flushes because of performance reasons. Any help is appreciated, thanks.
admin closed this issue 2026-01-22 14:52:04 +01:00
Author
Owner

@guilhermeblanco commented on GitHub (Dec 8, 2015):

Which version are you using? I have fixed this problem on master (aka. 2.6.0-dev)

@guilhermeblanco commented on GitHub (Dec 8, 2015): Which version are you using? I have fixed this problem on master (aka. 2.6.0-dev)
Author
Owner

@kilhage commented on GitHub (Dec 8, 2015):

I'm using 2.5.2, any plans of cherry picking this fix into 2.5.3 or do we have to wait until 2.6? When is this scheduled to be release?

I can verify that this problem is fixed in master!

@kilhage commented on GitHub (Dec 8, 2015): I'm using 2.5.2, any plans of cherry picking this fix into 2.5.3 or do we have to wait until 2.6? When is this scheduled to be release? I can verify that this problem is fixed in master!
Author
Owner

@Ocramius commented on GitHub (Dec 9, 2015):

In order to release 2.6, we still need to correct doctrine/data-fixtures#212 :-(

@Ocramius commented on GitHub (Dec 9, 2015): In order to release 2.6, we still need to correct doctrine/data-fixtures#212 :-(
Author
Owner

@mpdude commented on GitHub (Feb 20, 2023):

@kilhage it sounds as if this has been resolved, can you confirm that?

@mpdude commented on GitHub (Feb 20, 2023): @kilhage it sounds as if this has been resolved, can you confirm that?
Author
Owner

@mpdude commented on GitHub (Feb 27, 2023):

Your description is incomplete, for example it does not deal with the thumbnail

@mpdude commented on GitHub (Feb 27, 2023): Your description is incomplete, for example it does not deal with the `thumbnail`
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: doctrine/archived-orm#4924