This is only for projects using Hibernate with the L2 cache (but that 85% of generated projects!).
Currently, loading the current user uses the user login, for example in UserService.getUserWithAuthorities(). This is used by Spring Security and also when doing a an HTTP GET request on api/account - so this request is in fact quite common.
This is because we use the user's login in Spring Security, and not is ID. This could be discussed, but the idea is that:
So this all looks like a good idea, but as the Hibernate L2 cache uses the ID as the cache key, fetching a user by login means we go outside the cache. And as we usually also want the authorities, we also miss the authorities cache, and do an outer join to get the user+authorities.
This is isn't very good in terms of performance.
My proposal is that:
org.springframework.security.core.userdetails.User so we also store the User's ID in the Spring Security thread local objectSecurityUtils.getCurrentUserLogin() but which gets the current user ID (from the extended User in the previous point)-> we could then get the current user's ID directly, and then use it to get the User, instead of using the login. And that means we would go through the L2 cache, and solve the performance issue.
I've implemented this, as I had similar issues two years ago - and the commits lives on my master branch so I can contribute this.
Oh that's great @gzsombor - I just filled up the ticket so I don't forget this when I'm back from holidays, but if you're ready to do the PR, that's even easier :-)
As login is unique, wouldn't mark login field as a NaturalId(mutable=true) make Hibernate use it as a cache key as well?
They already provide an API for NaturalId fetch.
See documentation NaturalId
@NaturalId is a Hibernate specific annotation, I'm not sure we want to deviate from JPA standard.
Oh I didn't know that NaturalId was cached in L2 - thanks @Blackdread !!!!
mutable=true looks like calling for performance issues and/or bugs. The idea with the User entity is that you could change the login (it's the business key, and the ID is the technical key), but I'm not sure we allow that anywhere: maybe we could leave this immutable, and add some documentation in the code, to help people who would like to change this. I need to check this.Sorry to give bad feedback about the "NaturalId" solution:
So in the end it's not as easy as it looked at the beginning...
OK I'm going to use Spring Cache abstraction for this:
I'm committing the "Spring Cache" solution in the next 5 minutes:
This of course needs some testing, so that means I won't do a new release too soon.
Most helpful comment
OK I'm going to use Spring Cache abstraction for this: