E
E
Emprove2022-01-29 21:58:00
Doctrine ORM
Emprove, 2022-01-29 21:58:00

Why are all related entities updated when a record is created?

"laravel-doctrine/extensions": "1.4.0",
"laravel-doctrine/orm": "1.7.13",
"laravel/lumen-framework": "v8.3.4",

DOCTRINE_PROXY_AUTOGENERATE=true
DOCTRINE_CACHE=array
DOCTRINE_METADATA_CACHE= array
DOCTRINE_QUERY_CACHE=array
DOCTRINE_RESULT_CACHE=array

I turned on query logging in postgres 12 and saw that the doctrine updates a bunch of entities that I do not update in the code. For example, when adding a comment to an order, all links of the order itself are updated as well. As I understand it, unit of work does not work correctly. Here, even the last line is updated user, although my user is not updated anywhere from the code. The cascade annotations are nowhere to be found. I use flush(). If you do flush($entity) then everything works correctly, of course. But this is more of a crutch than a solution. I don't use clear() anywhere.

2022-01-29 15:29:31.141 UTC [674] LOG:  execute <unnamed>: INSERT INTO order_comments (id, created_at, updated_at, order_id, text, created_by) VALUES ($1, $2, $3, $4, $5, $6)
2022-01-29 15:29:31.141 UTC [674] DETAIL:  parameters: $1 = '28', $2 = '2022-01-29 18:29:31', $3 = '2022-01-29 18:29:31', $4 = '55', $5 = 'test', $6 = '1'
2022-01-29 15:29:31.142 UTC [674] LOG:  execute <unnamed>: UPDATE order_statuses SET id = $1, updated_at = $2 WHERE id = $3
2022-01-29 15:29:31.142 UTC [674] DETAIL:  parameters: $1 = '2', $2 = '2022-01-29 18:29:31', $3 = '2'
2022-01-29 15:29:31.142 UTC [674] LOG:  execute <unnamed>: UPDATE shipments SET id = $1, updated_at = $2 WHERE id = $3
2022-01-29 15:29:31.142 UTC [674] DETAIL:  parameters: $1 = '1', $2 = '2022-01-29 18:29:31', $3 = '1'
2022-01-29 15:29:31.143 UTC [674] LOG:  execute <unnamed>: UPDATE orders SET id = $1, shipment_id = $2, order_status_id = $3, cost = $4, updated_at = $5 WHERE id = $6
2022-01-29 15:29:31.143 UTC [674] DETAIL:  parameters: $1 = '55', $2 = '1', $3 = '2', $4 = '3343', $5 = '2022-01-29 18:29:31', $6 = '55'
2022-01-29 15:29:31.143 UTC [674] LOG:  execute <unnamed>: UPDATE order_has_products SET id = $1, price = $2 WHERE id = $3
2022-01-29 15:29:31.143 UTC [674] DETAIL:  parameters: $1 = '69', $2 = '3000', $3 = '69'
2022-01-29 15:29:31.144 UTC [674] LOG:  execute <unnamed>: UPDATE order_has_products SET id = $1, price = $2 WHERE id = $3
2022-01-29 15:29:31.144 UTC [674] DETAIL:  parameters: $1 = '70', $2 = '145', $3 = '70'
2022-01-29 15:29:31.144 UTC [674] LOG:  execute <unnamed>: UPDATE users SET id = $1, updated_at = $2 WHERE id = $3


UPD: brought out changesets and noticed that the dates are always updated. I have private ?\DateTime $created_at in all entities, and so on. And the changeset is always not empty, even if nothing is actually changed. As I understand it, you need to dig here: https://github.com/doctrine/orm/issues/7583

Answer the question

In order to leave comments, you need to log in

1 answer(s)
T
tukreb, 2022-01-30
@Emprove

Doctrine always updates an entity if it commits any of its changes.
The simplest example, for example, in the database, the date is written in one type of date, and when you retrieve it, you convert it in the object itself to another type of date.
Another example, in a database you have data in BIGINT, and doctrine converts it to a string when retrieved.
To avoid this, you need to make sure that the entity gets a ready-made data format that is completely identical to those stored in the database.
Perhaps you need to write your own data type.
https://www.doctrine-project.org/projects/doctrine...
Fix example for bigint

class BigIntType extends Type
{
    public function convertToPHPValue($value, AbstractPlatform $platform): ?int
    {
        return $value === null ? null : (int) $value; //до того как данные попали в сущность, мы насильно конвертируем в int (иначе будет строка)
    }

    public function getSQLDeclaration(array $column, AbstractPlatform $platform): string
    {
        return $platform->getBigIntTypeDeclarationSQL($column);
    }

    public function getName(): string
    {
        return Types::BIGINT;
    }
}

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question