IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Persistance des données Java Discussion :

Persistence d'un pattern "composite" avec JDO


Sujet :

Persistance des données Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Septembre 2008
    Messages
    71
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2008
    Messages : 71
    Par défaut Persistence d'un pattern "composite" avec JDO
    Mon propos est de créer une hiérarchie de classes destinées à représenter un arbre de données et de faire persister les données de ces classes via JDO (implémentation Kodo en version 4.1.4). Le modèle de classes est de fait basé sur un pattern "composite", celui-ci étant implémenté "dans les normes".

    Nous représentons donc un arbre de données. Les nœuds de l'arbre peuvent être de types concrets variés mais, classiquement, on distingue les nœuds ayant des enfants des nœuds feuilles.

    Les classes de bases sont celles qui permettent de créer la structure de l'arbre:
    • AbstractComponent: classe de base de toutes les classes considérées. Un "component" est donc un nœud de l'arbre de données au sens général. Tout nœud de l'arbre possède un parent, à l'exception du nœud racine pour lequel le parent est null.
    • AbstractComposite: classe représentant un nœud de l'arbre de données qui possède des enfants. Dérive évidemment de AbstractComponent.
    • AbstractLeaf: classe représentant un noeud feuille de l'arbre de données. Dérive également de AbstractComponent.


    Les sources de ces trois classes suivent.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    package test.jdo.composite;
     
    public abstract class AbstractComponent {
     
    	private long _id;
    	private AbstractComposite _parent;
     
    	public AbstractComponent() {
    		this(null);
    	}
     
    	public AbstractComponent(AbstractComposite composite) {
    		setParent(composite);
    	}
     
    	public AbstractComposite getParent() {
    		return _parent;
    	}
     
    	public long getId() {
    		return _id;
    	}
     
    	public void setParent(final AbstractComposite parent) {
     
    		if (parent != _parent) {
     
    			if (_parent != null) {
    				final AbstractComposite previous = _parent;
    				_parent = null;
    				previous.remove(this);
    			}
     
    			_parent = parent;
    		}
     
    	}
     
    	public void setId(final long id) {
    		_id = id;
    	}
     
    	public abstract boolean isLeaf();
     
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    package test.jdo.composite;
     
    import java.util.Iterator;
    import java.util.List;
     
    public abstract class AbstractComposite extends AbstractComponent {
     
    	private List<AbstractComponent> _children;
     
    	public AbstractComposite() {}
     
    	public AbstractComposite(final AbstractComposite parent) {
    		super(parent);
    	}
     
    	@Override
    	public boolean isLeaf() {
    		return false;
    	}
     
    	public int childrenCount() {
    		return _children.size();
    	}
     
    	public AbstractComponent childAt(final int index) {
    		return _children.get(index);
    	}
     
    	public boolean add(final AbstractComponent child) {
     
    		final boolean b = _children.add(child);
    		if (b)
    			child.setParent(this);
     
    		return b;
     
    	}
     
    	public boolean remove(final AbstractComponent child) {
     
    		final boolean b = _children.remove(child);
    		if (b)
    			child.setParent(null);
     
    		return b;
     
    	}
     
    	public AbstractComponent removeChildAt(final int index) {
     
    		final AbstractComponent child = _children.remove(index);
    		if (child != null)
    			child.setParent(null);
     
    		return child;
     
    	}
     
    	public Iterator<AbstractComponent> children() {
    		return _children.iterator();
    	}
     
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    package test.jdo.composite;
     
    public abstract class AbstractLeaf extends AbstractComponent {
     
    	public AbstractLeaf() {}
     
    	public AbstractLeaf(final AbstractComposite parent) {
    		super(parent);
    	}
     
    	@Override
    	public boolean isLeaf() {
    		return true;
    	}
     
    }
    Le code des classes concrètes n'a qu'une importance très minime dans ce cas. On en donne deux pour l'exemple.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    package test.jdo.composite.impl;
     
    import test.jdo.composite.AbstractComposite;
    import test.jdo.composite.AbstractLeaf;
     
    public class C1 extends AbstractComposite {
     
    	private int _anAttribute;
     
    	public C1() {}
     
    	public C1(AbstractComposite parent) {
    		super(parent);
    	}
     
    	public int getAnAttribute() {
    		return _anAttribute;
    	}
     
    	public void setAnAttribute(int n) {
    		_anAttribute = n;
    	}
     
    }
     
    public class C2 extends AbstractLeaf {
     
    	public C2() {}
     
    	public C2(AbstractComposite parent) {
    		super(parent);
    	}
     
    }
    Jusqu'ici, pas de difficultés. Le problème commence lorsqu'il s'agit de faire persister un arbre de données composé de ces éléments, ici de types C1 et C2.

    Un bon modèle candidat pourrait être dans ce cas celui qui est représenté sur la première image jointe. Un fichier package.jdo assez logique dans ce cas serait:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    <?xml version="1.0"?>
    <jdo>
     
    	<package name="test.jdo.composite">
     
    		<sequence
    			name="s_component"
    			datastore-sequence="S_COMPONENT"
    			strategy="contiguous" />
     
    		<class name="AbstractComponent" table="T_COMPONENT">
     
    			<inheritance strategy="new-table">
    				<discriminator strategy="value-map" indexed="true">
    					<column name="F_TYPE" jdbc-type="INTEGER" />
    				</discriminator>
    			</inheritance>
     
    			<field name="_id" primary-key="true" sequence="s_component">
    				<column name="F_ID" jdbc-type="BIGINT" />
    			</field>
    			<field name="_parent" persistence-modifier="persistent">
    				<column name="F_PARENT_ID" jdbc-type="BIGINT" />
    			</field>
     
    		</class>
     
    		<class name="AbstractComposite" table="T_COMPOSITE">
     
    			<inheritance strategy="subclass-table" />
     
    			<field
    				name="_children"
    				persistence-modifier="persistent"
    				mapped-by="AbstractComponent._parent">
    				<collection element-type="AbstractComponent" />
    			</field>
     
    		</class>
     
    		<class name="AbstractLeaf" table="T_LEAF">
    			<inheritance strategy="subclass-table" />
    		</class>
     
    	</package>
     
    	<package name="test.jdo.composite.impl">
     
    		<class name="C1" table="T_C1">
     
    			<inheritance strategy="new-table">
    				<discriminator strategy="final" value="1" />
    			</inheritance>
     
    			<field name="_anAttribute">
    				<column name="F_AN_ATTRIBUTE" jdbc-type="INTEGER" />
    			</field>
     
    		</class>
     
    		<class name="C2" table="T_C2">
     
    			<inheritance strategy="new-table">
    				<discriminator strategy="final" value="2" />
    			</inheritance>
     
    		</class>
     
    	</package>
     
    </jdo>
    Mais cette modélisation pose un problème de typage (assez logique au demeurant) entre les attributs AbstractComponent._parent et AbstractComposite._children... Sur lequel repose in fine toute la difficulté. Comment faire pour déclarer correctement la relation parent/enfant dans le cas d'un modèle de classe comme celui qui est proposé.

    J'ai bien essayé de générer un modèle avec une table par classe (i.e. en ajoutant des tables correspondant aux classes AbstractComposite et AbstractLeaf mais ca ne donne pas vraiment de résultat délirant (en plus de générer pas mal de jointures inutiles).

    Quelqu'un connait-il les "best-practices" pour traiter ce type de modèle de classes ?

    Merci d'avance...
    Images attachées Images attachées  

  2. #2
    Invité de passage
    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    1
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 1
    Par défaut
    Pardon, ceci n'est pas une réponse, mais plutôt je serai interressé par la réponse, j'ai le même pb.
    Cordialement

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo