Reputation: 1011
I know there're a lot of questions about join vs join fetch. The difference is explained as below:
A "fetch" join allows associations or collections of values to be initialized along with their parent objects using a single select. This is particularly useful in the case of a collection. It effectively overrides the outer join and lazy declarations of the mapping file for associations and collections.
However, when I have a Criteria or a HQL that uses an inner or outer join without fetching, I noticed that entities seem to be fully fetched (my hibernate mapping use FetchType.LAZY). I only expected this when I write ' join fetch'. So I don't see the difference in this case.
I must be missing something here. Can someone help me to clarify this please?
UPDATE
StringBuilder hql = new StringBuilder();
hql.append("select question ")
.append("from User as user ")
.append("left join user.definition as definition ")
.append("left join definition.sections as section ")
.append("left join section.questions as question ")
.append("where user.id = :user");
Query query = getQuery(hql.toString());
query.setParameter("user.id", userId);
return query.list();
When I inspect the first item of the question List I get the following:
questions = {java.util.ArrayList@6756} size = 18
[0]={model.Question@6800}"model.Question@10f98160[]"
section = {Section$$_javassist_21@6873}"model.Section@7711057b[]"
handler = {org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer@6890}
interfaces = {java.lang.Class[1]@6897}
constructed = true
persistentClass = {java.lang.Class@2708}"class model.Section"
getIdentifierMethod = null
setIdentifierMethod = null
overridesEquals = true
componentIdType = null
replacement = null
entityName = {java.lang.String@6898}"model.Section"
id = {java.lang.Long@6881}"1"
target = {model.Section@6899}"model.Section@7711057b[]"
name = {java.lang.String@6909}"General"
sequence = 1
textStart = {java.lang.String@6910}"Some value"
textEnd = null
sectionVersion = 1
status = {model.SectionStatus@6911}"ACTIVE"
definitions = {org.hibernate.collection.internal.PersistentSet@6912} size = 1
questions = {org.hibernate.collection.internal.PersistentSet@6913} size = 13
validFrom = {java.sql.Timestamp@6914}"2012-01-01 00:00:00.0"
validTo = {java.sql.Timestamp@6915}"2099-01-01 00:00:00.0"
active = false
uuid = {java.util.UUID@6916}"97277496-12ee-453d-9478-9fc4e1519c02"
id = {java.lang.Long@6881}"1"
version = {java.lang.Integer@6882}"1"
initialized = true
readOnly = false
unwrap = false
session = {org.hibernate.internal.SessionImpl@6900}"SessionImpl(PersistenceContext[entityKeys= [EntityKey[model.PossibleAnswer#57], EntityKey[model.PossibleAnswer#56], EntityKey[PossibleAnswer#59], E...readOnlyBeforeAttachedToSession = null sessionFactoryUuid = null specjLazyLoad = false
The Question class references to it's Section, in the stacktrace you can see that the Section is fully loaded although I didn't specify the 'join fetch' in my HQL.
Upvotes: 1
Views: 1837
Reputation: 691765
Don't use a debugger to test if an object is initialized. The debugger will call methods of your objects behind your back, to show the content of the object, and calling these methods will initialize the object.
Use Hibernate.isInitialized(question.getSection())
to test if the session is initialized.
Upvotes: 3