Les interfaces Java à la rescousse du fetching Hibernate
Monday, May 28th, 2007Dans mon travail de tous les jours, il m’arrive régulièrement de relire du code d’autrui. De manière générale, cela me transforme en un personnage grossier et passablement râleur (développement sans conscience n’est que ruine du code
). Néanmoins, il arrive parfois que je découvre au détour d’une classe une petite pépite d’ingéniosité, une manière à la fois simple et élégante de résoudre un problème sur lequel je me casse les dents depuis des mois ou des années. C’est donc le sourire aux lèvres que je vous livre ma dernière trouvaille ![]()
Chargement partiel Hibernate
Le chargement partiel des objets Hibernate (la fetching stategy) est un problème récurrent des développements mettant en œuvre cette librairie. La méthode que je préconise généralement au nom de ma société est de définir des méthodes de chargement explicites :
public void loadPerson(…) public void loadPersonAndAddress(…)
La critique la plus souvent formulée réside dans la quantité de code nécessaire au bon fonctionnement de cette solution : chaque méthode doit être écrite individuellement, ce qui présente une charge de travail non négligeable, surtout comparée aux chargements « lazy-loadés » (rien n’est chargé à priori) ou « eager-fetchés » (tout est chargé) qui présentent l’avantage de n’avoir qu’un seul point d’appel.
Utilisation des interfaces
L’utilisation conjointe des Criteria et des BeanUtils de Spring permet d’unifier les appels à la DAO avec la signature suivante :
public void loadPerson(…, Class fetchingInterface)
C’est l’interface qui porte les propriétés à charger :
public interface IPersonneAndAdresse
{
public Address getAddress() ;
public void setAddress(Address address);
}
On peut définir autant d’interface de chargement que de combinaison envisagée.
La méthode de chargement Hibernate ajoute quant à elle les jointures grâce à l’introspection :
PropertyDescriptor[] descriptors =
BeanUtils.getPropertyDescriptors(fetchingInterface);
// Add fetching criterion
for (PropertyDescriptor descriptor : descriptors)
{
criteria.setFetchMode(descriptor.getName(), FetchMode.JOIN);
}
C’est tout simple, mais néanmoins assez puissant. D’une part, cela permet de manipuler les jointures par simple ajout/suppression de méthodes dans l’interface, sans toucher au code de chargement Hibernate. On gagne en robustesse, et cette opération devient possible même pour un développeur ne maîtrisant pas les arcanes du fetching Hibernate.
D’autre part, il n’est nullement nécessaire que la classe du Domaine n’implémente cette interface. Dans ce cas, l’interface peut se concevoir comme un simple marqueur de chargement. Cependant, l’héritage permet caster la valeur de retour du chargement en cette interface, et ainsi éviter toute LazyInitializationException ultérieure.
That’s all folks !


French Scrum User Group
Agile Alliance
Valtech
planet Valtech
