Different behavior of Hibernate envers with and without byte-code enhancement

I’m trying to use byte-code enhancement for lazyinit.
I found difference result of hibernate envers when getting not audited property between Hibernate Proxy and LazyAttributeLoadingInterceptor(byte-code enhancer for lazy init)

My library versions are like below

hibernate-core:5.6.7.Final
hibernate-envers:5.6.7.Final

Here’s my Codes

@Audited
@Entity
public class ChildEntity{
    ...
    @OneToOne
    @NotAudited
    private ParentEntity parent;

}



public class Main{
    public static main(String[] ars){
        List<Object[]> resultList = (List<Object[]>) AuditReaderFactory.get(entityManager)
                          .createQuery()
                          .forRevisionsOfEntity(ChildEntity.class,false,true)
                          .add(AuditEntity.revisionNumber().between(~, ~))
                          .getResultList();

    ChildEntity childEntity = (ChildEntity) resultList.get(0)[0];


    //this is the point where LazyInit exception occurs
    childEntity.getParent();


   }
}

Whether I set enableLazyInitialization to true or false, I understand that the parent property in childEntity is set to null because it is not audited property.


when I set enableLazyInitialization to false, I don’t get any error for calling getter method of parent. I can get null value;
However, with enableLazyInitialization, true, I found that LazyInitializationException occrus in the same getter method.

package org.hibernate.bytecode.enhance.spi.interceptor;

public class EnhancementHelper {
    public static <T> T performWork(
			BytecodeLazyAttributeInterceptor interceptor,
			BiFunction<SharedSessionContractImplementor, Boolean, T> work,
			String entityName,
			String attributeName) {
		SharedSessionContractImplementor session = interceptor.getLinkedSession();

		boolean isTempSession = false;
		boolean isJta = false;


		if ( session == null ) {
			if ( interceptor.allowLoadOutsideTransaction() ) {
				session = openTemporarySessionForLoading( interceptor, entityName, attributeName );
				isTempSession = true;
			}
			else {
                //it goes to here
				throwLazyInitializationException( Cause.NO_SESSION, entityName, attributeName );
			}
		}
        ....
    }
}

trying to apply byte-code enhancement in my project, I thought hibernate will provide same result whether I turn on byte-code enhancement lazy init, or not . (Otherwise, it's too difficult to change lazy init strategy in ongoing project.)

Here’s my questions.

  1. Is there any misunderstanding for this issue
  2. is it bad idea to change lazy init strategy in my product-level project because there can be unexpected change in hibernate?
  3. If I can expect same behavior for the diff lazy init strategy, do you think this different result is hibernate bug? (which means it’s supposed to be fixed)

I really appreciate for your time!

Obviously bytecode enhancement will change how an application behaves since it allows deferring lazy loading further and even do lazy loading for some associations that proxying can’t provide.

If you rely on implicit actions to initialize your associations you might face such issues. It’s best if you use entity graphs, join fetches or explicit Hibernate.initialize() invocations if you want to make sure your code works correctly even with bytecode enhancement.

Even if this is a bug, Hibernate ORM 5.6 is not supported anymore. You have to update least to Hibernate ORM 6.6 if you seek any help.

1 Like