hibernate Proxy

hibernate Proxy

https://www.baeldung.com/hibernate-proxy-load-method


a proxy is “a function authorized to act as the deputy or substitute for another”.

This applies to Hibernate when we call Session.load() to create what is called an uninitialized proxy of our desired entity class.

Hibernate subclasses our entity class, using the CGLib library. Other than the @Id method, the proxy implementation delegates all other property methods to the Hibernate session to populate the instance, somewhat like:

public class HibernateProxy extends MyEntity {
private MyEntity target;

public String getFirstName() {
if (target == null) {
target = readFromDatabase();
}
return target.getFirstName();
}
}

Proxy and Lazy loading

Eg Employee albert = session.load(Employee.class, new Long(1));

Hibernate will create an uninitialized proxy of Employee. It will contain the ID that we gave it but otherwise will have no other values because we haven't hit the database yet.

once we call a method on albert:String firstName = albert.getFirstName();

Then Hibernate will query the employee database table for an entity with a primary key of 1, populating albert with his properties from the corresponding row.

one to many


public class Company {
private String name;
private Set<Employee> employees;
}

// testing
Company bizco = session.load(Company.class, new Long(1));
String name = bizco.getName();

we only queried for the company row, but the proxy will leave the employee set alone until we call getEmployees depending on the fetching strategy.

eager loading

using get

bypass proxies entirely and ask Hibernate to load the real thing using Session.get():

mployee finnigan = session.get(Employee.class, new Long(6)); , Will call the database right away, instead of returning a proxy.

While get() is convenient, load() can be lighter on the database.

Employee gerald = session.get(Employee.class, new Long(7));
Company worldco = (Company) session.load(Company.class, new Long(2));
employee.setCompany(worldco);
session.save(employee);

Since we know that we are only going to change the employee record in this situation, calling load() for Company is sensible.


The Proxy class is generated at runtime and it extends the original entity class. Hibernate uses Proxy objects for entities is for to allow lazy loading.

When accessing basic properties on the Proxy, it simply delegates the call to the original entity.

Every List, Set, Map type in the entity class is substituted by a PersistentList, PersistentSet, PersistentMap. These classes are responsible for intercepting a call to an uninitialized collection.

The Proxy doesn't issue any SQL statement. It simply triggers an InitializeCollectionEvent, which is handled by the associated listener, that knows which initialization query to issue (depends on the configured fetch plan).


https://xebia.com/blog/advanced-hibernate-proxy-pitfalls/

Proxies are the mechanism that allows Hibernate to break up the interconnected cloud of objects in the database into smaller chunks, that can easily fit in memory.

Pojo

public class Person {
private Long id;
private String name;
private Person boss;
private Set employees;
}

table rows

PERSON
ID NAME BOSS
1 Daan NULL
2 Vincent 1
3 Eelco 1
4 Jan 2
5 Maarten 3
6 Erik 3

if Hibernate loads the row with NAME=’Maarten’?

To store the data in memory, Hibernate will create a new Person object and set the columns to the fields. It stores the ID column in the id field and the NAME column in the name field.

Coming to the BOSS column, Hibernate faces a problem: The type of the column is NUMERIC, but the type of the property is Person. This is of course a foreign key, to another row in the PERSON table. Now, Hibernate could simply load the data from the associated row and create a new Person object and store it in the field, but this would cascade eventually to all rows in the table (and possibly other tables in the database), especially taking into account the employees property as well.

nstead of loading the associated row, Hibernate will create a Person object and set the id property to the value found in the BOSS column. This Person object is a specialized Person object, that will load the associated data if necessary. Initially the fields of this new Person object are not set, since the data is not yet loaded. When a method is invoked on the object, Hibernate will fetch the data from the column and populate the object. This is the proxy mechanism.

Screen Shot 2020-11-26 at 3.45.26 PM

Hibernate will create a dynamic subclass of Person using CGLib and add the desired functionality. We need a subclass of Person here, to comply with the type of the boss field.

Hibernate proxy can be easily identified by the class name, which will contain the “\(EnhancerByCGLIB\)” marker. This is due to the fact that the class is generated at runtime by CGLib.

http://storage.googleapis.com/xebia-blog/1/2008/03/image002.jpg

The most important is CGLIB$CALLBACK_0, which is set to an instance of CGLIBLazyInitializer, which is a Hibernate class. This is the object that enables the proxy to load the data when needed. It contains a “target” field, that will contain the Hibernate loaded object when the data is loaded


bytecode instrumentation

The bytecode enhancement can happen at:

Build-time

After the hibernate entities are compiled, the build tool (e.g. ANT, Maven) will insert bytecode level instructions into each compiled entity class. Because the classes are enhanced at build-time, this process exhibits no extra runtime penalty. Testing can be done against enhanced class versions, so that the actual production code is validated before the project gets built.

Runtime

The runtime weaving can be done using:

eg hibenate dirty check

Every time an entity is loaded, Hibernate makes an additional copy of all entity property values. At flush time, every managed entity property is matched against the loading-time snapshot value:

A more efficient approach would be to mark dirty properties upon value changing. Analogue to the original deep comparison strategy, it’s good practice to decouple the domain model structures from the change detection logic. The automatic entity change detection mechanism is a cross-cutting concern, that can be woven either at build-time or at runtime.

The entity class can be appended with bytecode level instructions implementing the automatic dirty checking mechanism.