matrei opened a new issue, #16659:
URL: https://github.com/apache/grails-core/issues/16659
### Summary
With GORM for Hibernate 7, Hibernate logs a warning at startup for every
lazy many-to-one association that has no fetch mapping:
```
WARN org.hibernate.orm.core : HHH000510: Association with '@Fetch(JOIN)' and
'fetch=FetchType.LAZY' found. This is interpreted as lazy:
NavigableRole[pingcrm.Contact].account
WARN org.hibernate.orm.core : HHH000510: Association with '@Fetch(JOIN)' and
'fetch=FetchType.LAZY' found. This is interpreted as lazy:
NavigableRole[pingcrm.Contact].organization
WARN org.hibernate.orm.core : HHH000510: Association with '@Fetch(JOIN)' and
'fetch=FetchType.LAZY' found. This is interpreted as lazy:
NavigableRole[pingcrm.Organization].account
WARN org.hibernate.orm.core : HHH000510: Association with '@Fetch(JOIN)' and
'fetch=FetchType.LAZY' found. This is interpreted as lazy:
NavigableRole[pingcrm.auth.UserRole#{id}].role
WARN org.hibernate.orm.core : HHH000510: Association with '@Fetch(JOIN)' and
'fetch=FetchType.LAZY' found. This is interpreted as lazy:
NavigableRole[pingcrm.auth.UserRole#{id}].user
```
The associations are plain properties such as `Account account`, which GORM
maps as lazy by default. Hibernate still loads them lazily, so the behaviour is
correct, but every application gets one warning per association, for mappings
the application did not write.
Seen with Grails 8.0.0, `grails-data-hibernate7` 8.0.0 and Hibernate
7.4.10.Final.
### Cause
`ManyToOneValuesBinder.bindManyToOneValues` sets the fetch mode and laziness
of a many-to-one separately:
```java
var fetchMode =
Optional.ofNullable(config.getFetchMode()).orElse(FetchMode.DEFAULT);
manyToOne.setFetchMode(fetchMode);
manyToOne.setLazy(property.isLazy());
```
Without a fetch mapping, the association gets `FetchMode.DEFAULT` and `lazy
= true`.
In Hibernate 7.4, `FetchOptionsHelper.determineFetchStyleByMetadata` turns
`FetchMode.DEFAULT` for a to-one into `FetchStyle.JOIN` when the associated
entity is not batch loadable and has no proxy (`!persister.hasProxy()`).
`determineFetchTiming` then finds a JOIN style on a lazy association, logs
HHH000510 and returns `FetchTiming.DELAYED`:
```java
case JOIN: {
if ( lazy ) {
CORE_LOGGER.fetchModeJoinWithLazyWarning( role );
return FetchTiming.DELAYED;
}
return FetchTiming.IMMEDIATE;
}
```
Associations mapped as eager, such as one with
`fetchStrategy(FetchType.EAGER)`, are not lazy and do not log the warning.
### Workaround
Mapping the fetch mode of the association as `SELECT` avoids the warning:
```groovy
import org.hibernate.FetchMode
static final MappingDefinition<Mapping, PropertyConfig> mapping =
MappingBuilder.orm {
property('organization') {
fetch = FetchMode.SELECT
}
}
```
With this mapping, the warning for `Contact.organization` is no longer
logged, while the ones for the other associations still are. This has to be
done for every lazy many-to-one association, though, including those of plugin
domain classes.
### Suggested fix
When no fetch mode is mapped, `ManyToOneValuesBinder` could use
`FetchMode.SELECT` for a lazy association, the fetch mode that matches lazy
loading, and keep `FetchMode.DEFAULT` for an eager one. Lazy loading with a
`SELECT` fetch mode is the combination Hibernate expects, so it would not warn,
as the workaround shows.
I have not tried the change in GORM itself, only the equivalent mapping in
an application.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]