Objects merged into the persistence context via callback method are not flushed

I have observed a strange/unexpected behavior when trying to update an object using the JPA callback methods of another object.

The updated object is not flushed even it is explicitly merged into the persistence context. A persisted object instead is flushed as expected. In the example below, I stripped down everything from my code to give an example for the problem.

in class ExternalJob (an entity bean):

@PostUpdate
public void postUpdate() {
     CDI.current().select(ExternalJobService.class).get().executePostUpdate(getId());
}

in class ExternalJobService (a stateless session bean):

public void executePostUpdate(Long id) {
    // 1) newly created object of a differen class JobLog is flushed after the method has ended and thus the transaction committed
    entityManager.persist(new JobLog(...));

    // 2) but an update on an existing object of a different class JobLog is NOT flushed
    JobLog joblog = find(JobLog.class, 11099L);
    joblog.setLog(LocalDateTime.now());
    entityManager.merge(joblog);
}

Is this a Hibernate bug or is my expectation is wrong? Many thanks in advance for some clarifying feedback.

By the way: I am on Hibernate Version 5.4.30.Final

I doubt that the JPA specification clearly defines if this should work, but I understand that it is desirable. Please create an issue in the issue tracker(https://hibernate.atlassian.net) with a test case(https://github.com/hibernate/hibernate-test-case-templates/blob/master/orm/hibernate-orm-5/src/test/java/org/hibernate/bugs/JPAUnitTestCase.java) that reproduces the issue.

Many thanks for your response. It would be a great help if somebody who is deep in Hibernate could simple tell whether there is a difference in the treatment of persisted and merged entites in the flush handling when the merge/persist is invoked via a callback method such @PreUpdate/Post-Update.

Thanks in advance.

PS: I am not sure whether I am able to deliver a reproducer (soon).

I am deep in Hibernate, but not that particular part of the code. Anyway, I just had a quick look into the code and it seems to me that this is totally unsupported and if it happens to work, then this is only by accident. If you look into org.hibernate.engine.spi.ActionQueue#executeActions(org.hibernate.engine.spi.ExecutableList<E>) where the execution happens, the ExecutableList is iterated, but the iterator does not handle that elements could be added to the list while iterating org.hibernate.engine.spi.ExecutableList#iterator.

From what I can see, it depends at which phase you interact with the EntityManager. In the best case, the changes will happen in the next flush if you flush explicitly. Otherwise, the operations would just be ignored.

dear @beikov many thanks for your very helpful answer.

would this not be valid feature request for Hibernate to ensure by default that all objects either added by persist() or merge() to the persistence context are included into the corresponding flush of the corresponding transaction - even though this issue is not finally/fully specified by the standard?

reading the following callback method description are naturally leading to expectation that they should be executed within the boundaries of the current transaction - although i am fully aware that this is not stated explicitly here.

Type Description
PrePersist Executed before the entity manager persist operation is actually executed or cascaded. This call is synchronous with the persist operation.
PreRemove Executed before the entity manager remove operation is actually executed or cascaded. This call is synchronous with the remove operation.
PostPersist Executed after the entity manager persist operation is actually executed or cascaded. This call is invoked after the database INSERT is executed.
PostRemove Executed after the entity manager remove operation is actually executed or cascaded. This call is synchronous with the remove operation.
PreUpdate Executed before the database UPDATE operation.
PostUpdate Executed after the database UPDATE operation.
PostLoad Executed after an entity has been loaded into the current persistence context or an entity has been refreshed.

Like I stated before, I understand that this is a desirable feature, but it’s just not supported yet. To be honest, without community involvement it’s probably going to take quite some time as our main priority is to deliver Hibernate 6.0 first. So please create an issue in the issue tracker(https://hibernate.atlassian.net) with a test case(https://github.com/hibernate/hibernate-test-case-templates/blob/master/orm/hibernate-orm-5/src/test/java/org/hibernate/bugs/JPAUnitTestCase.java ) that shows how this should work, or even better, add that to the hibernate test suite and provide a PR with the tests: GitHub - hibernate/hibernate-orm: Hibernate's core Object/Relational Mapping functionality