📜 ⬆️ ⬇️

JPA entity proxying method for client (anti-lazy initialization)

Recently, when I saw on Habré a post about the fight against lazy initialization in Hibernate, I became interested - I read the post itself and waited until I had more comments - would anyone suggest the way in which we solved this problem. I did not see anything like it. Way under the cut.

I will describe by example. Suppose there is an entity:
@Entity public class Person { @Id private long id; private String firstName; private String lastName; @OneToMany private List<Person> children; // getters-setters } 

We want to ensure that when the presentation of this entity is sent to the client, the children list is initialized and, moreover, does not pull any Hibernate garters. To do this, we declare the following interface:
 public interface IPerson { public long getId(); public void setId(long id); // getters-setters for firstName/lastName public List<IPerson> getChildren(); public void setChildren(List<IPerson> children); } 

This is the presentation that will be sent to the client. Note that Person does not implement IPerson. And the client does not even know about the existence of Person. For it, there are only its various representations in the form of interfaces. Proxy looks like this:
 Person examplePerson = getPersonFromDb(); IPerson personProxy = ProxyFactory.getProxy(IPerson.class, examplePerson); 

How it works? The ProxyFactory.getProxy () method creates, using the dynamic proxy mechanism, the implementation of the IPerson interface, whose handler contains a Map with field values. To populate this map, ProxyFactory reads the reflection of the examplePerson entity field. Accordingly, when any getter / setter handler is called on the interface, it climbs into this map.

Naturally, an entity may have several interfaces, and a proxy may contain only part of the fields. For a situation with a list (as in the example List <IPerson>), you can also specifically specify which proxies the list consists of (for example, List <IPersonOnlyWithName>).

In order to check the proxy interfaces (that the interface really corresponds to the entity) occurred at the compilation stage for Eclipse, a simple Ant-builder was written, which runs along the entities that were annotated as follows:
 @Entity @ProxyBinding(interfaceClass = IPerson.class) public class Person { // … } 

This approach has proven its viability in practice and has acquired a large number of various supplements. It would be interesting to see some constructive criticism and comments.

')

Source: https://habr.com/ru/post/112621/


All Articles