Lazy collection returns uninitialized proxy despite having full entity in 2nd-level cache

Hi. In our app business data is associated with dictionary entities via join tables.
I’m trying to improve the performance of my app and I made some dictionary entities cacheable. Lookup by id now works as expected, but I thought that Hibernate would also make the lazy collection SQL smaller and take the @Basic fields of dictionary entities from the cache, but it didn’t happen.

After that I marked the @Basic dictionary fields as lazy and repeated my tests. Now indeed the lazy collection SQL only selects the dictionary id and the other side id from the join table, but there’s a new problem: if the dictionary entity was never looked up by id in the current Session, then taking it from the lazy collection returns an uninitialized proxy and accessing its fields causes another SQL! Is it possible to make the lazy collection load objects from second level cache?

                final Set<Language> lazyCollection = book.getBookLanguages();
                // Uncomment to load from 2nd-level cache into Session:
                // findLang(em, 1L);
                // findLang(em, 2L);
                // findLang(em, 3L);

                // good:
                // select bl1_0."bookid",bl1_1."id" from "b2l" bl1_0 join "TestCache2$Language"
                // bl1_1 on bl1_1."id"=bl1_0."langid" where bl1_0."bookid"=?
                lazyCollection.size();
                for (final Language lang : lazyCollection) {
                    final long id = lang.getId();
                    // bad:
                    // select l1_0."code",l1_0."name" from
                    // "TestCache2$Language" l1_0 where l1_0."id"=?
                    lang.getCode();
                }

Upd: In org.hibernate.sql.results.graph.entity.AbstractEntityInitializer.resolveEntityInstance I see that entityDescriptor.canUseReferenceCacheEntries() (“hibernate.cache.use_reference_entries”) should do what I need, but when I apply this setting, 2lc stops working completely for the Language entity because of java.io.NotSerializableException: snippet.TestCache2$Language. After adding “implements Serializable” the error changes to NotSerializableException: org.hibernate.persister.entity.SingleTableEntityPersister

isolated project to reproduce

Like I told you in Hibernate.initialize() does not initialize lazy @Basic fields, it’s probably better to use a DTO mapping for this instead.

I see though that your mapping is unnecessarily complex. You do see that initializing the collection causes a join to the target table? So you don’t gain anything from making the attributes in Language lazy.
I don’t understand why you are making name and code lazy, but I would suggest you to not do that. If you care about caching the collection, you can annotate the collection with the @Cache annotation. Also see the documentation