watchme
watchme

Reputation: 740

Spring-data-jpa - When does .save() not return the same entity?

In this code I am saving the main object and a foreign key of that object. I print out "entity" and "thing" which should be the exact same object. But they aren't. Why?

thingList.forEach(entity -> {
            System.out.println(entity);

            // Save if the foreign key exists and isn't already saved in the database
            if(entity.ForeignKey() != null && ForeignKeyRepository.findOne(entity.ForeignKey().getId()) == null)
            {
                ForeignKeyRepository.save(entity.getForeignKey());
            }
            Thing thing = thingRepository.save(entity);
            System.out.println(thing);
        });

Upvotes: 4

Views: 9515

Answers (2)

Jens Schauder
Jens Schauder

Reputation: 81990

If the entity is not new and there is already a different instance representing the database row in the session of the EntityManager you get that instance, modified to match the one passed as an argument, as the return value.

You can confirm this by inspecting the implementation and the relevant JPA documentation.

The save method is implemented in SimpleJpaRepository

public <S extends T> S save(S entity) {

    if (entityInformation.isNew(entity)) {
        em.persist(entity);
        return entity;
    } else {
        return em.merge(entity);
    }
}

em is the EntityManager. From it's merge methods documentation:

Returns: the managed instance that the state was merged to

The JPA specification section 3.2.7.1 is a little more explicit:

• If X is a detached entity, the state of X is copied onto a pre-existing managed entity instance X' of the same identity or a new managed copy X' of X is created.

• If X is a new entity instance, a new managed entity instance X' is created and the state of X is copied into the new managed entity instance X'.

• If X is a removed entity instance, an IllegalArgumentException will be thrown by the merge operation (or the transaction commit will fail).

• If X is a managed entity, it is ignored by the merge operation, however, the merge operation is cascaded to entities referenced by relationships from X if these relationships have been annotated with the cascade element value cascade=MERGE or cascade=ALL annotation.

Upvotes: 6

elmehdi
elmehdi

Reputation: 479

That is what excepted as they mention in the doc of the save method

S save(S entity) : Saves a given entity. Use the returned instance for further operations as the save operation might have changed the entity instance completely.

Upvotes: 0

Related Questions