Maven and Gradle Hibernate Enhance Plugin
Are you struggling with performance issues in your Spring, Jakarta EE, or Java EE application?
What if there were a tool that could automatically detect what caused performance issues in your JPA and Hibernate data access layer?
Wouldn’t it be awesome to have such a tool to watch your application and prevent performance issues during development, long before they affect production systems?
Well, Hypersistence Optimizer is that tool! And it works with Spring Boot, Spring Framework, Jakarta EE, Java EE, Quarkus, Micronaut, or Play Framework.
So, rather than fixing performance issues in your production system on a Saturday night, you are better off using Hypersistence Optimizer to help you prevent those issues so that you can spend your time on the things that you love!
Introduction
In this article, I’m going to explain how the configure the Maven and Gradle Hibernate Enhance Plugin.
The goal of the Hibernate Enhance plugin is to instrument the JPA entity bytecode in order to improve the effectiveness and efficiency of the associated data access operations.
Maven Hibernate Enhance Plugin
For Maven, Hibernate offers the hibernate-enhance-maven-plugin that allows you to enable JPA entity bytecode enhancement.
So, in your project pom.xml Maven configuration file, you need the following plugin:
<plugin>
<groupId>org.hibernate.orm.tooling</groupId>
<artifactId>hibernate-enhance-maven-plugin</artifactId>
<version>${hibernate.version}</version>
<executions>
<execution>
<configuration>
<enableLazyInitialization>true</enableLazyInitialization>
<enableDirtyTracking>true</enableDirtyTracking>
<enableAssociationManagement>true</enableAssociationManagement>
<enableExtendedEnhancement>false</enableExtendedEnhancement>
</configuration>
<goals>
<goal>enhance</goal>
</goals>
</execution>
</executions>
</plugin>
Gradle Hibernate Enhance Plugin
If you’re using Gradle, then in the build.gradle configuration file, you need to add the following plugin in order to enable the JPA entity bytecode enhancement mechanism.
plugins {
id "org.hibernate.orm" version hibernateVersion
}
Last, in order to configure the execution of the bytecode enhancement plugin, you need to add a configuration that is specific to the Hibernate version that you’re using.
Hibernate 6 or later
hibernate {
enhancement {
enableLazyInitialization = true
enableDirtyTracking = true
enableAssociationManagement = true
enableExtendedEnhancement = false
}
}
Hibernate 5
For Hibernate 5, use the following configuration:
hibernate {
enhance {
enableLazyInitialization = true
enableDirtyTracking = true
enableAssociationManagement = true
enableExtendedEnhancement = false
}
}
Configuring the Maven and Gradle Hibernate Enhance Plugin
As you have already seen, there are four properties you can configure:
enableLazyInitializationenableDirtyTrackingenableAssociationManagementenableExtendedEnhancement
By default, all these settings are set to the value of false, so if you need to enable a given bytecode enhancement setting, you have to do it explicitly.
Maven and Gradle Hibernate Enhance Plugin – enableLazyInitialization
By setting the enableLazyInitialization to true, Hibernate changes the bytecode of the getter and setter methods to intercept the call and trigger the property initialization on demand.
So, the entity class Java Bean getter and setter methods are going to be changed from this:
public PostDetails getDetails() {
return details;
}
public void setDetails(PostDetails details) {
this.details = details;
}
to this:
public PostDetails getDetails() {
return this.$$_hibernate_read_details();
}
public void setDetails(PostDetails details) {
this.$$_hibernate_write_details(details);
}
public PostDetails $$_hibernate_read_details() {
if (this.$$_hibernate_getInterceptor() != null) {
this.details = (PostDetails) this.$$_hibernate_getInterceptor()
.readObject(
this,
"details",
this.details
);
}
return this.details;
}
public void $$_hibernate_write_details(PostDetails details) {
if (this.$$_hibernate_getInterceptor() != null) {
this.details = (PostDetails) this.$$_hibernate_getInterceptor()
.writeObject(
this,
"details",
this.details,
details
);
} else {
this.details = (PostDetails) details;
}
}
The $$_hibernate_getInterceptor method that’s being called looks as follows:
public PersistentAttributeInterceptor $$_hibernate_getInterceptor() {
return this.$$_hibernate_attributeInterceptor;
}
And the $$_hibernate_attributeInterceptor object is defined like this:
@Transient private transient PersistentAttributeInterceptor $$_hibernate_attributeInterceptor;
So, as you can see, the bytecode has changed significantly.
For more details about the
enableLazyInitializationbytecode enhancement option and how you can use it to load entity attribute lazily, check out the following two articles:
Maven and Gradle Hibernate Enhance Plugin – enableDirtyTracking
The enableDirtyTracking option allows you to record which properties have changed so that the Hibernate dirty checking mechanism gets the list of changes without having to inspect every property via Java Reflection.
Once you activate the enableDirtyTracking option, you will see that the entity property Java Beans setters are changed like this:
public void setDetails(PostDetails details) {
this.$$_hibernate_write_details(details);
}
public void $$_hibernate_write_details(PostDetails details) {
if (!Objects.deepEquals(details, this.details)) {
this.$$_hibernate_trackChange("details");
}
this.details = details;
}
The $$_hibernate_trackChange method looks as follows:
public void $$_hibernate_trackChange(String property) {
if (this.$$_hibernate_tracker == null) {
this.$$_hibernate_tracker = new SimpleFieldTracker();
}
this.$$_hibernate_tracker.add(property);
}
The SimpleFieldTracker will then store the entity properties that were modified and provide this information to the dirty checking mechanism when the Persistence Context is flushed.
Maven and Gradle Hibernate Enhance Plugin – enableAssociationManagement
The enableAssociationManagement option tries to address the requirement of synchronizing both sides of a bidirectional association.
So, instead of relying on you to provide addChild and removeChild methods in the parent entity, Hibernate changes the setter methods:
public void setDetails(PostDetails details) {
this.$$_hibernate_write_details(details);
}
public void $$_hibernate_write_details(PostDetails details) {
if (this.details != null && Hibernate.isPropertyInitialized(
this.details,
"post" ) &&
details == null) {
((PostDetails)this.details).$$_hibernate_write_post((Post)null);
}
this.details = details;
if (details != null && Hibernate.isPropertyInitialized(details, "post") &&
((PostDetails)details).$$_hibernate_read_post() != this) {
((PostDetails)details).$$_hibernate_write_post(this);
}
}
The
enableAssociationManagementcannot intercept changes happening in a collection of child entities, and, for this reason, you are better off using theaddChildandremoveChildmethods.
Maven and Gradle Hibernate Enhance Plugin – enableExtendedEnhancement
The enableExtendedEnhancement option allows the bytecode enhancement mechanism to instrument methods beyond getter and setters.
So, consider that your entity has the following utility method:
public boolean contains(PostComment comment) {
return this.comments.contains(comment);
}
If you enable the enableExtendedEnhancement option, the Hibernate can enhance this method as well:
public boolean contains(PostComment comment) {
return this.$$_hibernate_read_comments().contains(comment);
}
This will allow you to initialize or track changes happening to entity properties even outside the scope of getter or setter methods.
When it comes to getter and setters, the method definition is rather straightforward, and the automatic bytecode instrumentation outcome can be deterministic. However, other methods might be more complex, and if you enable the enableExtendedEnhancement option, it could be that the bytecode enhancement mechanism makes unintended changes, so you should be very careful when enabling this option.
If you enjoyed this article, I bet you are going to love my Book and Video Courses as well.
Conclusion
The Maven Gradle Hibernate Enhance Plugin allows you to instrument the JPA entity properties so that you can enable property-level lazy loading, track changes, or synchronize bidirectional associations.







Brilliant plugin,
would it be possible for it to annotate the methods it creates with a custom annotation?
For the lazy loading and dirty checking enhancements, the bytecode changes happen inside the methods, so there is no annotation involved. What is your use case that would require a custom annotation?
Thanks for your reply.
Ah silly me, of course, the $$_hibernate methods don’t actually come from the enhancement library but from hibernate itself!
So I guess it is about annotating all generated methods in Hibernate. The use case is to be able to exclude them in JaCoCo reports, that seems to only offer class exclusions.
I still think it would be better if JaCoCo offered method exclusion, but I’m exploring all avenues.
For now, I just exclude the package where all my entities live and avoid adding any logic in that package…
The $$_hibernate part is injected by the Hibernate BE mechanism. I wonder what is the problem with those methods from a JaCoCo perspective.