Home Java A way to proxy JPA entities to the client (fighting lazy initialization)

A way to proxy JPA entities to the client (fighting lazy initialization)

by admin

Recently, after seeing on Habra post about fighting with lazy initialization in Hibernate, I got interested – I read the post itself and waited until there were more comments, to see if somebody would suggest the way we solved this problem. Nothing like that, I did not see. Here is the way.
I will describe it using an example. Suppose there is an entity :

@Entitypublic class Person {@Idprivate long id;private String firstName;private String lastName;@OneToManyprivate List<Person> children;// getters-setters}

We want to ensure that when the representation of this entity is sent to the client, the children list is initialized and, moreover, does not pull any Hibernate hooks. To do this, declare the following interface :

public interface IPerson {public long getId();public void setId(long id);// getters-setters for firstName/lastNamepublic List<IPerson> getChildren();public void setChildren(List<IPerson> children);}

This is the representation that will be sent to the client. Note that Person does not implement IPerson. And the client doesn’t know that Person exists at all. He only has his different representations as interfaces. The proxying looks like this :

Person examplePerson = getPersonFromDb();IPerson personProxy = ProxyFactory.getProxy(IPerson.class, examplePerson);

How does it work? The ProxyFactory.getProxy() method creates, using the dynamic proxy mechanism, an implementation of the IPerson interface, which has a Map with the field values in its handle. To fill this map, ProxyFactory reads the fields of the examplePerson entity by reflection. Accordingly, when some getter/setter is called on the interface, the handler goes into this map.
Of course, an entity can have multiple interfaces and proxies can contain only part of the fields. For a list situation (as in the example List<IPerson> ) you can also specify which proxies make up the list (e.g. List<IPersonOnlyWithName> ).
In order to check the proxy interfaces (that the interface really corresponds to an entity) at compile time, a simple Ant-builder was written for eclipse, which goes over the entities annotated as follows :

@Entity@ProxyBinding(interfaceClass = IPerson.class)public class Person {// ...}

This approach has proven to be viable in practice and has been overgrown with a wide variety of additions. It would be interesting to see some constructive criticism and comments.

You may also like