L'intérêt de l'attribut calculé hibernate est de déporter un calcul inter-objet de la JVM vers la base de donnée elle même.

Prenons un cas théorique. Nous avons une liste d'objet à afficher. Pour chaque objet nous devons afficher, ou pas, une option suivant une règle métier. Cette règle métier lie certains objets à d'autres suivant des caractéristiques communes. Plutôt que de charger tous les objets et de faire un calcul dans la JVM pour savoir si chacun des objets correspond ou non à la règle métier -ce qui prendrait trop de ressources au serveur d'application- nous pouvons créer un attribut calculé sur notre objet du domaine. Sur notre attribut calculé nous fixons une requête Sql qui permettra de réaliser le calcul de la règle métier côté base de donnée. Ainsi, en une requête effectué depuis la JVM, nous obtenons toutes les informations dont nous avons besoin pour afficher ou non les options.

Le gain en terme de performance est significatif et les bases de données ont les capacités pour traiter ce genre de calcul de manière particulièrement efficace, alors pourquoi s'en priver ?

Un exemple d'un bean hibernate auquel on applique un attribut calculé grâce à l'annotation Formula:

@Entity
public MonBean {
  .. // Divers champs, par exemple un champs annee
  private int annee;
  // ajouter un getter hibernate et un setter pour le champs annee
  ..
  /** Le champs calculé. */
  private long champsCalule;
  /** Getter de l'attribut caluclé. */
  @Formula("select count(*) from nomDuBean b where b.annee=annee")
  public long getChampsCalcule() {
  }
  /** setter du champs calule. */
  public void setChampsCalucle(long valeur) {
    this.champsCalucle = valeur;
  }
  // un getter qui va nous permettre d'obtenir un boolean utilisable directement dans notre vue (la page JSF par exemple)
  @Transient
  public boolean isValide() {
    return (champsCalule > 2) ? true : false;
  }
}

Dans cette exemple, lorsque nous récupérerons le bean de la base de donnée il n'y aura qu'un appel à la BDD. La requête relative au champs calculé sera effectuée par la base et les résultats seront retournés d'un coup à la JVM. On peut également utiliser un attribut Transient -qui ne sera pas mappé- afin de traduire le champs calculé en un boolean qui sera facilement utilisable dans une vue.

La requête Sql qui se trouve sur le champs calculé, permet de compter le nombre de MonBean par année. Ainsi, au niveau de la vue, si nous souhaitons afficher un bouton que si le nombre de MonBean par année est supérieur à 2 il suffira d'utiliser le getter isValide pour afficher ou non ce bouton.

J'espère que vous utiliserez cette technique à bon escient. N'hésitez pas à utiliser des sondes au niveau de la base de donnée afin de vérifier que vos requêtes soient effectivement bien optimisées.