After migrating from Spring Boot 2.7 to Spring Boot 3, this warning appears in the logs when executing a query with lock:
"HHH000444: Encountered request for locking however dialect reports that database prefers locking be done in a separate select (follow-on locking); results will be locked after initial query executes"
I checked the Hibernate version, which also changed during the migration
before migration: org.hibernate:hibernate-core:5.6.15.Final.
after migration: org.hibernate.orm:hibernate-core:6.2.13.Final.
Here are sample queries I have, there are several and they all look quite similar to these:
@Transactional(propagation = Propagation.MANDATORY)
@Lock(LockModType.PESSIMISTIC_WRITE)
@Query("SELECT n FROM #{#name} n WHERE n.id = ?1")
T findById(UUID id);
I also tried to force this warning to be disabled with query hints by adding such an annotation to methods: @QueryHints(value = { @QueryHint(name = "hibernate.query.followOnLocking", value = "false") }, forCounting = false)
But that didn’t help either, and the warning still appears. (I am using a PostgreSQL database)
And they write that in version 6.2.3.Final there was a bug that caused follow-on locking and it has been fixed, however this kind of warning appears and I don’t know what the bug really means and why it appeared.
It is possible that you’re seeing this warning if you’re using an entity-graph for the query that causes a left join to be created in the SQL. Since for update locking doesn’t work in PostgreSQL when using left joins, Hibernate ORM will use follow-on locking and hence emit this warning.
Another possible reason for left joins to be generated is that you’re fetching an entity that has an association which is a @OneToOne(mappedBy = "...") or a @XToOne with @NotFound.
Show the HQL queries that Spring generates and passes to Hibernate ORM as well as the SQL queries that are generated by Hibernate ORM.
Since for update locking doesn’t work in PostgreSQL when using left joins, Hibernate ORM will use follow-on locking and hence emit this warning.
Referring to this, has this always been the case in Hibernate, or was it only introduced in version 6? Well, since I didn’t get any warning in version 5 (so what could have really changed in the new version (?))
Hi @beikov we are using hibernate-core:6.4.1.Final and postgresql DB, we have an entity A which have @ManyToOne association with entity B (without @NotFound). We still are facing this warning and the sql generated is left join. Now what is happening that we are facing lost update concurrency problem. The transactions are using jakarta.persistence.EntityManager#find(Class<T> entityClass, Object primaryKey, LockModeType lockMode) with PESSIMISTIC_WRITE lock.
Below is the sql trace -
==== txn 1 =====
2024-02-06 01:19:37.554 [ThreadPoolTaskExecutor-2] [] WARN - org.hibernate.sql.results.jdbc.internal.DeferredResultSetAccess HHH000444: Encountered request for locking however dialect reports that database prefers locking be done in a separate select (follow-on locking); results will be locked after initial query executes
Hibernate:
select
a1_0.a_id,
a1_0.b_id,
b1_0.b_id,
b1_0.name,
b1_0.status,
a1_0.dummy_col
from
entity_a a1_0
left join
entity_b b1_0
on b1_0.b_id=a1_0.b_id
where
a1_0.a_id=?
Hibernate:
select
b_id
from
entity_b
where
b_id=? for update
Hibernate:
select
a_id
from
entity_a
where
a_id=? for update
==== txn 2 ====
Hibernate:
select
a1_0.a_id,
a1_0.b_id,
b1_0.b_id,
b1_0.name,
b1_0.status,
a1_0.dummy_col
from
entity_a a1_0
left join
entity_b b1_0
on b1_0.b_id=a1_0.b_id
where
a1_0.a_id=?
Hibernate:
select
b_id
from
entity_b
where
b_id=? for update
Both txns are using same method, however txn2 hangs (after step over through EntityManger.find()) with these 2 sql queries when txn1 has already taken lock on the row. After txn1 commits, txn2 fires
Hibernate:
select
a_id
from
entity_a
where
a_id=? for update
Lost updates weren’t there in hibernate 5.6.15.Final which we were using ealier, neither this warning.
Many thanks for any help