Salut,
Afin d'implémenter une gestion utilisateur multi-rôles, j'ai utilisé le pattern décorateur sur cet ensemble d'objets :
- ActorAbs (objet abstrait [abstract] )
- ActorCrt (objet concret [extends ActorAbs] )
- ActorDecoratorAbs (décorateur abstrait [abstract, extends ActorAbs] )
- TeacherDecoratorCrt (décorateur concret [extends ActorDecoratorAbs])
- PupilDecoratorCrt (décorateur concret [extends ActorDecoratorAbs])
La création d'un utilisateur (Actor), ayant les rôles d'élève mais également d'enseignant, se fait comme suit :
La sauvegarde d'un utilisateur dans la base fonctionne bien : en utilisant un générateur d'identifiants "hilo", l'enregistrement dans la table 'teacherdecorator' reçoit l'identifiant '1', la table 'pupildecorator' reçoit l'identifiant '2', etc., jusqu'à atteindre l'objet concret non-décoré (ActorCrt).
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 Actor actor; actor = null; actor = new ActorCrt(); actor = actor.decorate(PupilDecoratorCrt.class); actor = actor.decorate(TeacherDecoratorCrt.class);
L'enregistrement de cet utilisateur renvoit donc l'identifiant '1', que je stocke.
Par contre, logiquement, un problème survient lors du chargement d'un utilisateur depuis la base.
Lors du chargement, les rôles attribués à l'utilisateur sont inconnus, la seule chose dont nous disposons est son identifiant dans la base.
Aussi, je tente de charger l'utilisateur ainsi :
Fournir l'identifiant à l'utilisateur de base en vue du chargement me semble être la seule solution possible (on ne peut présumer à l'avance de la nature de l'utilisateur), mais çà ne peut pas marcher ainsi, car l'identifiant de l'utilisateur n'est pas référencé dans la table de l'utilisateur de base (bas de la pile), mais dans celle du rôle 'teacherdecorator' (haut de la pile), si l'on reprend l'exemple ci-dessus.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 Actor actor; actor = null; actor = new ActorCrt(); actor.setId(new Long("1")); actor.load();
Est-ce un mauvais choix de programmation ?
Voilà, je n'ai pas jugé utile de poster tout le code, sachant que le problème est plus conceptuel qu'autre chose.
Pour le moment, j'envisage les solutions suivantes :
- utilisation du même identifiant d'enregistrement pour chacun des rôles d'un même acteur ( 'teacherdecorator' (1) --> 'pupildecorator' (1) --> 'actorcrt' (1) )
Si cette solution est possible, pouvez-vous m'expliquer comment la mettre en oeuvre (quel générateur utiliser, foreign, etc.). J'ai lu que l'on ne peut pas avoir deux fois le même identifiant dans une même session, même pour des enregistrements de tables différentes.
- retourner l'identifiant de l'objet de base (et non pas celui de l'objet décoré), puis utiliser des associations bidirectionnelles pour remonter à l'objet décoré. Par exemple : pour 'teacher --> pupil --> actor' = '1 --> 2 --> 3', réussir à retourner '3' (au lieu de '1' à l'heure actuelle). Cependant, mes essais de retourner l'identifiant de l'objet de base dans les méthodes 'getId()' de chaque décorateur m'ont menés à l'erreur 'identifier was altered from <id> to <id>'.
- recherche explicite de l'identifiant dans un ensemble de tables candidates [teacher, pupil, etc.]
Cette solution est d'ailleurs vouée à l'échec : si une décoration 'teacher --> pupil --> actor' a les identifiants '1 --> 2 --> 3' et qu'une autre décoration successive 'teacher --> pupil --> actor' reçoit donc les identifiants '2 --> 3 --> 4', la recherche de l'identifiant n°2 dans les tables 'teacher' et 'pupil' sera incapable de distinguer à quel table l'objet appartient.
Si possible, je souhaite éviter les associations bidirectionnelles et le générateur 'foreign', car ils sont sources de code "inutile/dédié Hibernate" dans les classes Java (exemple : si une classe Voiture est composée d'une instance de Roue (voir 4 instances, çà roule mieux), il est dommage de devoir garder une référence sur la classe Voiture dans une méthode 'getVoiture()' de la classe Roue).
Que me conseillez-vous ?
Merci.
Partager