1

I have a Person class which has a lazy inited collection named autos. After fetch person from database I invoked two hibernate methods named isInitialized(autos) and isPropertyInitialized(personObject,autos) the first shows false, the second one shows true. why?

@Entity
public class Person {

    @OneToMany(mappedBy="person",fetch=FetchType.LAZY)
    private List<Auto> autos;

}


@Entity
public class Auto {

    @ManyToOne
    @JoinColumn(name = "person_id", nullable = false)
    private Person person;

}

The test code:

Person p = personRepository.findAll().get(0);     
System.out.println(Hibernate.isInitialized(p.getAutos()));
System.out.println(Hibernate.isPropertyInitialized(p,"autos"));

console:

false
true
beatrice
  • 3,684
  • 5
  • 22
  • 49
  • 1
    mat be some information https://stackoverflow.com/questions/1589144/is-there-a-helper-to-know-whether-a-property-has-been-loaded-by-hibernate – Ryuzaki L Nov 09 '19 at 13:52
  • thanks. Already tried it with a field as non collection: @OneToOne(mappedBy="person",fetch=FetchType.LAZY) private Auto autos; Still returns true, the first one returns false – beatrice Nov 09 '19 at 13:55

1 Answers1

4

I believe in this case usage of Hibernate.isPropertyInitialized could be not correct.

According to the documentation Hibernate.isPropertyInitialized should be used to verify laziness for attributes or state e.g. "name" for Person object. To verify laziness of subentities Hibernate.isInitialized should be used

boolean personInitialized = Hibernate.isInitialized(person);

boolean personBooksInitialized = Hibernate.isInitialized(person.getBooks());

boolean personNameInitialized = Hibernate.isPropertyInitialized(person, "name");

Or preferably as it's mentioned in the documentation javax.persistence.PersistenceUtil.isLoaded

PersistenceUtil persistenceUnitUtil = Persistence.getPersistenceUtil();

boolean personInitialized = persistenceUnitUtil.isLoaded(person);

boolean personBooksInitialized = persistenceUnitUtil.isLoaded(person.getBooks());

boolean personNameInitialized = persistenceUnitUtil.isLoaded(person, "name");

Now why there is Hibernate.isPropertyInitialized and why it's returning always true I believe the main reason is the Bytecode enhancement and lazy attribute loading.

Typically when fetching an entity all attributes are loaded e.g. "name", "age" etc.

When fetching an entity, all attributes are going to be loaded as well. This is because every entity attribute is implicitly marked with the @Basic annotation whose default fetch policy is FetchType.EAGER. source

However, with the Bytecode enhancement, we can define which of the attributes should be lazy. This useful when we have some large attributes like blob image. I believe for this particular scenario we need Hibernate.isPropertyInitialized

Why in your case it's always returning true. If we take a look at the Java Doc of the method we could see that it expects

@param proxy The potential proxy

If it's HibernateProxy then it will be checked if it's uninitialized. If yes you will receive false since for proxy laziness all attributes are eagerly initialized, thus proxy is uninitialized then attributes are as well. On the other hand, we have a statement

 @return true if the named property of the object is not listed as uninitialized; false otherwise

So in your case, you are not using the lazy attribute fetching mechanism and not passing the proxy object since Person is already initialized. There is no way to check if the property is listed as uninitialized, therefore true is returned.

vzhemevko
  • 815
  • 8
  • 25
  • If you are using compile-time enhancement, `person.getBooks()` will throw exception. Is there any other way to check if it is initialized? – hurelhuyag Dec 16 '21 at 13:39