Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hibernate collections initialized on call to getMyCollection #17291

Closed
fabrii opened this issue May 17, 2021 · 13 comments · Fixed by #17365 or #17435
Closed

Hibernate collections initialized on call to getMyCollection #17291

fabrii opened this issue May 17, 2021 · 13 comments · Fixed by #17365 or #17435
Assignees
Milestone

Comments

@fabrii
Copy link
Contributor

fabrii commented May 17, 2021

Describe the bug

Hibernate.isInitialized(proxy) function is not working properly.

Expected behavior

Return true when the object is initialized.
Return false when the object is not initialized.

Actual behavior

Returns true always.

To Reproduce

Steps to reproduce the behavior:

  1. Create an entitiy "a", with a OneToMany Lazy Collection.
  2. logger.log(Level.INFO, "Is initialized?: " + Hibernate.isInitialized(a.getCollection()));

Environment:

Output of uname -a or ver

Linux fabricio-desktop 5.4.0-73-generic #82-Ubuntu SMP Wed Apr 14 17:39:42 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

Output of java -version

openjdk version "11.0.11" 2021-04-20
OpenJDK Runtime Environment (build 11.0.11+9-Ubuntu-0ubuntu2.20.04)
OpenJDK 64-Bit Server VM (build 11.0.11+9-Ubuntu-0ubuntu2.20.04, mixed mode, sharing)

Quarkus version or git rev

1.11.3 and 1.13.4

Build tool (ie. output of mvnw --version or gradlew --version)

Apache Maven 3.6.3
Maven home: /usr/share/maven
Java version: 11.0.11, vendor: Ubuntu, runtime: /usr/lib/jvm/java-11-openjdk-amd64
Default locale: es_ES, platform encoding: UTF-8
OS name: "linux", version: "5.4.0-73-generic", arch: "amd64", family: "unix"

@fabrii fabrii added the kind/bug Something isn't working label May 17, 2021
@quarkus-bot
Copy link

quarkus-bot bot commented May 17, 2021

/cc @Sanne, @gsmet, @yrodiere

@yrodiere yrodiere self-assigned this May 18, 2021
@yrodiere
Copy link
Member

Thank you for your report.

Unfortunately, I was not able to reproduce your problem with the provided information. In my tests, Hibernate.isInitialized() returns false as expected.

Please provide a minimal project reproducing the problem.

You can for example use this one as the base of your reproducer, changing whatever is necessary to reproduce your problem: https://github.com/yrodiere/quarkus-playground/tree/hibernate-isinitialized

@yrodiere yrodiere added the triage/needs-reproducer We are waiting for a reproducer. label May 18, 2021
@fabrii
Copy link
Contributor Author

fabrii commented May 18, 2021

Hi! You just need to change this line:

Containing containing = entityManager.getReference(Containing.class, id);

by

Containing containing = entityManager.find(Containing.class, id);

@Sanne
Copy link
Member

Sanne commented May 18, 2021

@fabrii that would invalidate the test: find is not allowed to return a lazily initialized object - it needs to load the real object.

@Sanne Sanne added triage/invalid This doesn't seem right and removed kind/bug Something isn't working labels May 18, 2021
@fabrii
Copy link
Contributor Author

fabrii commented May 18, 2021

@Sanne

We are calling Hibernate.isInitialized(containing.getContained()); (The lazy collection)

Not Hibernate.isInitialized(containing);

@yrodiere
Copy link
Member

@Sanne I must admit I'm a bit surprised; is find supposed to load lazy collections? It should not return a proxy, that's for sure, but loading lazy collections as well seems a bit... too much?

@Sanne
Copy link
Member

Sanne commented May 18, 2021

ah sorry sure - I was only referring to the object itself, my bad I misunderstood.

@fabrii
Copy link
Contributor Author

fabrii commented May 18, 2021

From my experience using Quarkus, when using find the collections are lazy (no querys are fired to the database to load them), but the Hibernate.isInitialized returns true anyway.

@yrodiere yrodiere removed triage/needs-reproducer We are waiting for a reproducer. triage/invalid This doesn't seem right labels May 18, 2021
@yrodiere
Copy link
Member

From what I can see, Hibernate.isInitialized is right: the collection was initialized. It shouldn't have been, though, and that is a bug.

I opened https://hibernate.atlassian.net/browse/HHH-14620 upstream.

@plevart
Copy link
Contributor

plevart commented Sep 1, 2022

Hi, what's the state of this? I'm using Quarkus 2.11.2 which uses Hibernate 5.6.10 and I still trigger some Hibernate Session interaction by calling myEntity.getMyFetchTypeLazyCollection() while Hibernate.isInitialized(myEntity) == true. Since this happens in a custom serializer when the Session is not active any more, it triggers Hibernate exception. Here's the relevant part of stack trace:

Caused by: org.hibernate.LazyInitializationException: Unable to perform requested lazy initialization [eu.otlm.ferengi.hibernate.model.Tower$E.spanB] - no session and settings disallow loading outside the Session
        at org.hibernate.bytecode.enhance.spi.interceptor.EnhancementHelper.throwLazyInitializationException(EnhancementHelper.java:275)
        at org.hibernate.bytecode.enhance.spi.interceptor.EnhancementHelper.performWork(EnhancementHelper.java:165)
        at org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor.loadAttribute(LazyAttributeLoadingInterceptor.java:80)
        at org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor.fetchAttribute(LazyAttributeLoadingInterceptor.java:76)
        at org.hibernate.bytecode.enhance.spi.interceptor.LazyAttributeLoadingInterceptor.handleRead(LazyAttributeLoadingInterceptor.java:57)
        at org.hibernate.bytecode.enhance.spi.interceptor.AbstractInterceptor.readObject(AbstractInterceptor.java:153)
        at eu.otlm.ferengi.hibernate.model.Tower$E.$$_hibernate_read_spanB(Tower.java)
        at eu.otlm.ferengi.hibernate.model.Tower$E.getSpanB(Tower.java:64)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

...and here's the part of the entity with mapping annotations:

        @Override
        @OneToMany(targetEntity = Span.E.class, mappedBy = "towerB", fetch = FetchType.LAZY)
        public Set<Span> getSpanB() {
            return spanB;
        }

It looks like although the Tower$E proxy should be initialized as Hibernate.isInitialized(tower) == true, calling .getSpanB() on it still triggers Hibernate Session interaction. Shouldn't this already be fixed?

@yrodiere
Copy link
Member

yrodiere commented Sep 1, 2022

@plevart No, the fact that your entity is initialized does not mean its associations are. You spanB association is lazy, so unless you access it before closing your session, that lazy init exception is expected.

If you want to discuss this further, please open a GitHub discussion or a bug report. Reviving old topics is not a great way to get visibility to your comments ;)

@plevart
Copy link
Contributor

plevart commented Sep 1, 2022

Sorry, I incorrectly assumed this issue was still open.

@plevart
Copy link
Contributor

plevart commented Sep 1, 2022

I posted this here: #27657

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment