We moved to hibernate 6 (along with Spring Boot 3) and have some performance problems.
Our entity looks like this:
@Entity
public class MobileDeviceToken {
@Id
private int id = 0;
@NaturalId
private String dienst;
@NaturalId
private String token;
private String deviceName;
private ZonedDateTime registrierungsdatum = ZonedDateTime.now();
...
}
And we use this method to load all MobileDeviceTokens like this:
@Repository
public interface MobileDeviceTokenRepository extends JpaRepository<MobileDeviceToken, Integer> {
@Query(value = "select * from mobiledevicetoken where registrierungsdatum > ?1", nativeQuery = true)
List<MobileDeviceToken> fetchNewMobileDeviceTokensFromDatabase(ZonedDateTime datum);
}
We load 50.000 entries it takes 10 seconds with hibernate 5.x and 3 hours(!) with hibernate 6.x. When we remove both @NaturalID
annotations, it is as fast as with hibernate 5.x again.
The SQL is still as fast as before but the hibernate loading of all elements takes hours instead of seconds.
Profiling the process we saw a lot of operations regarding NaturalIds and putting the elements into a ConcurrentHashMap. I guess hibernate is putting the elements into the session cache. Somehow it seems that hibernate is comparing each element with all the others. So for 50.000 elements it has to run more than a billion operations.
Just removing @NaturalId
removes this performance bottleneck immediately. As we do not load anything byNaturalId the annotation was useless for us.
Has something changed in hibernate 6.x regarding NaturalIDs? I would like to understand what happens here.