Les classes persistantes sont les classes d'une application qui implémentent les entités d'un problème métier (ex. Client et Commande dans une application de commerce électronique). Toutes les instances d'une classe persistante ne sont pas forcément dans l'état persistant - au lieu de cela, une instance peut être éphémère (NdT : transient) ou détachée.
Hibernate fonctionne de manière optimale lorsque ces classes suivent quelques règles simples, aussi connues comme le modèle
de programmation Plain Old Java Object (POJO). Cependant, aucune de ces règles ne sont des besoins absolus. En effet, Hibernate3
suppose très peu de choses à propos de la nature de vos objets persistants. Vous pouvez exprimer un modèle de domaine par
d'autres moyens : utiliser des arbres d'instances de Map
, par exemple.
Toute bonne application Java nécessite une classe persistante représentant les félins.
package eg; import java.util.Set; import java.util.Date; public class Cat { private Long id; // identifier private Date birthdate; private Color color; private char sex; private float weight; private int litterId; private Cat mother; private Set kittens = new HashSet(); private void setId(Long id) { this.id=id; } public Long getId() { return id; } void setBirthdate(Date date) { birthdate = date; } public Date getBirthdate() { return birthdate; } void setWeight(float weight) { this.weight = weight; } public float getWeight() { return weight; } public Color getColor() { return color; } void setColor(Color color) { this.color = color; } void setSex(char sex) { this.sex=sex; } public char getSex() { return sex; } void setLitterId(int id) { this.litterId = id; } public int getLitterId() { return litterId; } void setMother(Cat mother) { this.mother = mother; } public Cat getMother() { return mother; } void setKittens(Set kittens) { this.kittens = kittens; } public Set getKittens() { return kittens; } // addKitten not needed by Hibernate public void addKitten(Cat kitten) { kitten.setMother(this); kitten.setLitterId( kittens.size() ); kittens.add(kitten); } }
Il y a quatre règles à suivre ici :
Cat
a un constructeur sans argument. Toutes les classes persistantes doivent avoir un constructeur par défaut (lequel peut ne
pas être public) pour qu'Hibernate puissent les instancier en utilisant Constructor.newInstance()
. Nous recommandons fortement d'avoir un constructeur par défaut avec au moins une visibilité paquet pour la génération du proxy à l'exécution dans Hibernate.
Cat
possède une propriété appelée id
. Cette propriété mappe la valeur de la colonne de clé primaire de la table d'une base de données.La propriété aurait pu s'appeler
complètement autrement, et son type aurait pu être n'importe quel type primitif, n'importe quel "encapsuleur" de type primitif,
java.lang.String
ou java.util.Date
. (Si votre base de données héritée possède des clés composites, elles peuvent être mappées en utilisant une classe définie
par l'utilisateur et possédant les propriétés associées aux types de la clé composite - voir la section concernant les identifiants
composites plus tard).
La propriété d'identifiant est strictement optionnelle. Vous pouver l'oublier et laisser Hibernate s'occuper des identifiants de l'objet en interne. Toutefois, nous ne le recommandons pas.
En fait, quelques fonctionnalités ne sont disponibles que pour les classes déclarant un identifiant de propriété :
Transitive reattachment for detached objects (cascade update or cascade merge) - see Section 10.11, « Persistance transitive »
Session.saveOrUpdate()
Session.merge()
Nous recommandons que vous déclariez les propriétés d'identifiant de manière uniforme. Nous recommandons également que vous utilisiez un type nullable (ie. non primitif).
Une fonctionnalité clef d'Hibernate, les proxies, nécessitent que la classe persistente soit non finale ou qu'elle soit l'implémentation d'une interface qui déclare toutes les méthodes publiques.
Vous pouvez persister, grâce à Hibernate, les classes final
qui n'implémentent pas d'interface, mais vous ne pourrez pas utiliser les proxies pour les chargements d'associations paresseuses
- ce qui limitera vos possibilités d'ajustement des performances.
Vous devriez aussi éviter de déclarer des méthodes public final
sur des classes non-finales. Si vous voulez utiliser une classe avec une méthode public final
, vous devez explicitement désactiver les proxies en paramétrant lazy="false"
.
Cat
déclare des mutateurs pour toutes ses champs persistants. Beaucoup d'autres solutions de mapping Objet/relationnel persistent
directement les variables d'instance. Nous pensons qu'il est bien mieux de fournir une indirection entre le schéma relationnel
et les structures de données internes de la classe. Par défaut, Hibernate persiste les propriétés suivant le style JavaBean,
et reconnaît les noms de méthodes de la forme getFoo
, isFoo
et setFoo
. Nous pouvons changer pour un accès direct aux champs pour des propriétés particulières, si besoin est.
Les propriétés n'ont pas à être déclarées publiques - Hibernate peut persister une propriété avec un paire de getter/setter de visibilité par défault,
protected
ou private
.