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

Hibernate Java Discussion :

Mapping de relations one-to-many et inverse


Sujet :

Hibernate Java

  1. #1
    Invité
    Invité(e)
    Par défaut Mapping de relations one-to-many et inverse
    Bonjour,

    J'ai la relation suivante :
    Un article est contenu dans un groupe et un groupe peux conteni différentes articles.

    J'ai mapper le set d'articles de mon groupe et tout fonctionne bien, j'obtiens sans problèmes tous les articles contenus dans un groupe. Mais je voudrais également obtenir le groupe auquel mon article appartient mais la ça ne marche plus.
    Voici mes mappings :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    <class name="test.hib.Article" table="articles">
            <id name="id" column="id">
                <generator class="native" />
            </id>
            <many-to-one name="group" 
            			column="groupId" lazy="false" />
    </class>
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    <class name="test.hib.Group" table="groups">
            <id name="id" column="id">
                <generator class="native" />
            </id>
            <set name="articles">
            	<key column="groupId" not-null="true" />
            	<one-to-many class="test.hib.Article" />
            </set>
    </class>
    Pouvez-vous m'aiguiller un peu sur les relations à utiliser de chaque côté ?

    Merci

  2. #2
    Membre éprouvé Avatar de Gardyen
    Homme Profil pro
    Bio informaticien
    Inscrit en
    Août 2005
    Messages
    637
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Bio informaticien

    Informations forums :
    Inscription : Août 2005
    Messages : 637
    Points : 1 050
    Points
    1 050
    Par défaut
    le mapping de group est correct mais il me semble qu'il manque l'attribut class dans ton fichier article:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    <class name="test.hib.Article" table="articles">
            <id name="id" column="id">
                <generator class="native" />
            </id>
            <many-to-one name="group" class="test.hib.Group"
            			column="groupId" lazy="false" />
    </class>
    à part ça ce sont les bonnes relations, du moins tant qu'un article ne peut appartenir qu'à un seul groupe

  3. #3
    Invité
    Invité(e)
    Par défaut
    Bonjour,

    Merci pour la correction. Maintenant ça à l'air de fonctionner mais le champ "groupId" de ma table "articles" reste toujours vide.. Donc, bien évidemment lorsque je tente de récupérer un groupe, il ne contient pas d'articles et un article n'a pas de référence à son groupe.

    J'ai toujours les même mappings que dans le premier post mais j'ai rajouté la classe comme le conseille 'Gardyen' et supprimé le "not-null" car je peux avoir des groupes sans articles.

    Avec quelques syso dans mes accesseurs j'ai ceci à la console
    // J'ai insérer mes deux articles (Lampe et Vase) et le groupe sans
    // aucuns articles et tout est bon en DB
    // J'ai ajouté les articles dans le groupe et je mets à jour le groupe :
    INSERT DATAS
    DEBUG [main] test.dao.DAOFactory - getting group dao
    DEBUG [main] test.dao.impl.spring.hibernate.GenericHibernateDao - Updating Group 'Mon groupe'.
    --> Mon groupe : getArticles():[Lampe, Vase]
    --> Mon groupe : getArticles():[Lampe, Vase]

    // Juste pour le plaisir j'affiche les articles de mon groupe
    Listing :
    [3] Mon groupe
    --> Mon groupe : getArticles():[Lampe, Vase]
    [5] Lampe
    [4] Vase

    // Je récupère le groupe via son id
    SELECT DATAS
    DEBUG [main] test.dao.DAOFactory - getting group dao
    --> Mon groupe : setArticles([])
    --> Mon groupe : getArticles():[]
    DEBUG [main] test.dao.impl.spring.hibernate.GenericHibernateDao - Getting group with key '3' return 'Mon groupe'.

    // J'affiche le contenu du groupe
    [3] Mon groupe
    --> Mon groupe : getArticles():[]
    Comme on peux le voir à la récupération Hibernate fais un setArticles d'une collection vide ("--> Mon groupe : setArticles([])").
    Si je rajoute "not-null="true"" alors j'ai une exception.

    Je ne vois vraiment pas ou est le problème.. Pouvez-vous m'aider ?

    Edit : Si je fais un save() au lieu d'un update du groupe, le résultat est le même -> Pas d'articles ans le groupe
    Dernière modification par Invité ; 08/04/2008 à 10h47.

  4. #4
    Membre éprouvé Avatar de Gardyen
    Homme Profil pro
    Bio informaticien
    Inscrit en
    Août 2005
    Messages
    637
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Bio informaticien

    Informations forums :
    Inscription : Août 2005
    Messages : 637
    Points : 1 050
    Points
    1 050
    Par défaut
    tu peux donner le code que tu utilises pour ton test ?

  5. #5
    Invité
    Invité(e)
    Par défaut
    pour info : Je travaille avec Spring aussi.

    Voici le code de mon test. Les beans n'ont rien d'intéressant, juste le fait que l'ajout d'un article dans un groupe ajoute automatiquement ce groupe à l'article et inverse..
    Le dao vas suivre
    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
     
    ApplicationContext ctx = new FileSystemXmlApplicationContext("src/applicationContext.xml");
    DAOFactory daof = (DAOFactory) ctx.getBean("daoFactory");
     
    Group grp1 = new Group("Mon groupe");
    Integer id = daof.getGroupDao().save(grp1);
     
    Article article0 = new Article("Lampe");
    daof.getArticleDao().save(article0);
    Article article1 = new Article("Vase");
    daof.getArticleDao().save(article1 );
     
    // la méthode addArticle de Group fais automatiquement un setGroup(this) sur 
    // le paramètre 'article' et inverse :
    // article.setGroup(grp) { this.group=grp; if(!grp.getArticles().contains(this)) grp.setArticle(this); } ) 
    // group.addArticle(article) { this.articles.add(article); article.setGroup(this); }
    grp1.addArticle(article0);
    grp1.addArticle(article1);
     
    System.out.println("\n INSERT DATAS");
    daof.getGroupDao().update(grp1);
     
    System.out.println("\n["+grp1.getId()+"] "+grp1+"");
    for (Article article : grp1.getArticles()) {
        System.out.println("\t["+article.getId()+"]  "+article+" "+article.getGroup()+")");
    }
     
    System.out.println("\n SELECT DATAS");
    Group grp = daof.getGroupDao().get(id);
     
    System.out.println("\n["+grp.getId()+"] "+grp+"");
    for (Article article : grp1.getArticles()) {
        System.out.println("\t["+article.getId()+"]  "+article+" "+article.getGroup()+")");
    }
    Tous les daos de mon test héritent de celui-ci sans surcharger quoi que ce soit.
    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
     
    public class GenericHibernateDao<T , PK extends Serializable> extends HibernateDaoSupport {
     
    	protected final static Logger logger = Logger.getLogger();
     
    	private Class<T> type;
     
    	public GenericHibernateDao(Class<T> type) {
    		this.type = type;
    	}
     
    	/** Store an object to the storage and return the generated key */
    	@SuppressWarnings("unchecked")
    	public PK save(T object) throws DataAccessException {
    		PK key = (PK) getHibernateTemplate().save(object);
    		logger.debug("Saving %s '%s' with key '%s'.", type.getSimpleName(), object, key);
    		return key;		 
    	}
     
    	/** 
             * Retrieve an object that was previously saved to the storage using the 
             * indicated key as primary key.
             */
    	@SuppressWarnings("unchecked")
    	public T get(PK key) throws DataAccessException {
    		T object = (T) getHibernateTemplate().get(type, key);
    		logger.debug("Getting %s with key '%s' return '%s'.", type.getSimpleName(), key, object);
    		return object;
    	}
     
    	/** Save changes made to an object */
    	public void update(T object) throws DataAccessException {
    		logger.debug("Updating %s '%s'.", type.getSimpleName(), object);
    		getHibernateTemplate().update(object);	
    	}
     
    	/** Remove an object from the storage */
    	public void remove(T object) throws DataAccessException {
    		logger.debug("Removing "+object);
    		getSession().delete(object);
    	}
    }
    MERCI

  6. #6
    Membre éprouvé Avatar de Gardyen
    Homme Profil pro
    Bio informaticien
    Inscrit en
    Août 2005
    Messages
    637
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Bio informaticien

    Informations forums :
    Inscription : Août 2005
    Messages : 637
    Points : 1 050
    Points
    1 050
    Par défaut
    hum est ce que tu utilises des transactions ?

    j'avais ce genre de problèmes quand je ne les utilisais pas ou quand j'oubliais de commiter...

    le getHibernateTemplate te renvoie une Session non ?

  7. #7
    Invité
    Invité(e)
    Par défaut
    Le getHibernateTemplate() me renvoie un HibernateTemplate (http://static.springframework.org/sp...eTemplate.html)
    Justement en regardant la javdoc je vois qu'ils préconisent une autre façon de faire (sans passer par HibernateTemplate) je tente ça tout de suite..

    Non, je n'utilise pas de transactions (pour le moment) mais il serait logique de les utiliser. Peux tu m'aiguiller un peu sur la façon de faire ?

    Pense-tu que celà sois la cause de mes ennuis ?


    Edit : Bon hé bien c'est encore pire qu'avant. Cette fois j'ai cette exception :
    org.hibernate.HibernateException: No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here
    at org.springframework.orm.hibernate3.AbstractSessionFactoryBean$TransactionAwareInvocationHandler.invoke(AbstractSessionFactoryBean.java:300)
    at $Proxy0.getCurrentSession(Unknown Source)
    at be.gervaisb.sics.dao.impl.spring.hibernate.GenericHibernateDao.save(GenericHibernateDao.java:40)
    at test.TestDao.main(TestDao.java:45)
    Dernière modification par Invité ; 08/04/2008 à 12h29.

  8. #8
    Membre éprouvé Avatar de Gardyen
    Homme Profil pro
    Bio informaticien
    Inscrit en
    Août 2005
    Messages
    637
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Bio informaticien

    Informations forums :
    Inscription : Août 2005
    Messages : 637
    Points : 1 050
    Points
    1 050
    Par défaut
    voilà à quoi ressemble une portion de code dans mon système:

    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
     
    Session session = null;
    Transaction transaction = null;
    try {
    	// Session
    	session = HibernateUtil.getSession();
    	transaction = session.beginTransaction();
     
    	// Do some stuff
     
    	// Close
    	transaction.commit();
    } catch (Exception e) {
    	if (transaction != null) {
    		try {
    			transaction.rollback();
    		} catch (HibernateException he) {
    			logger.error("Cannot rollback transaction", he);
    		}
    	}
    } finally {
    	if (session != null && session.isOpen()) {
    		try {
    			session.close();
    		} catch (HibernateException he) {
    			logger.error("Cannot close session normally", he);
    		}
    	}
    }
    HibernateUtil est une classe 'utilitaire' chargée de créer ou de renvoyer la session courante. on peut la trouver un peu partout, par exemple dans ce topic

    il faut aussi déclarer la transaction factory dans ton hibernate.cfg.xml
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    <property name="hibernate.transaction.factory_class">
    	org.hibernate.transaction.JDBCTransactionFactory
    </property>
    tout ça c'est pour une configuration "à la main", Spring doit avoir tout ce qu'il faut pour utiliser les transactions

    enfin pour ton erreur je dirais que ta Session n'a pas encore été créée, il doit y avoir un appel à SessionFactory.openSession() avant d'utiliser getCurrentSession()

  9. #9
    Invité
    Invité(e)
    Par défaut
    j'ai rajouté le propriété mais j'au toujors la même erreur. D'après toi ce serais donc le fait de ne pas utiliser de transaction qui pose problème ?
    Si c'est le cas il faudars que je me tourne vers Spring pour comprendre la cause de l'erreur et ensuite tenter les transactions..

  10. #10
    Invité
    Invité(e)
    Par défaut
    Voilà, j'ai sollutionné mon problème. Je démarre une transaction avant le save, l'update et le get et fais un commit une fois terminé mais le résultat reste le même -> Pas de sauvegrade des relations..

  11. #11
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Points : 48 804
    Points
    48 804
    Par défaut
    Juste comme çà, si un article n'est contenu que dans un seul groupe (ce que ton post d'origine laisse supposer), c'est pas un many-to-one que tu dois utiliser pour le mapping article -> groupe, mais un simple property:

    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
     
    <class name="test.hib.Group" table="groups">
            <id name="id" column="id">
                <generator class="native" />
            </id>
            <set name="articles">
            	<key column="groupId" not-null="true" />
            	<one-to-many class="test.hib.Article" />
            </set>
    </class>
     
    <class name="test.hib.Article" table="articles">
            <id name="id" column="id">
                <generator class="native" />
            </id>
            <property name="group" column="groupId"/>
    </class>

  12. #12
    Invité
    Invité(e)
    Par défaut m'enfin !!
    m'enfin !!!

    Voilà, ça tourne bien maintenant.. J'ai modifie l'ordre de mon test :
    1° Je crée et sauve un groupe sans articles
    2° Je crée les articles, les ajoute dans le groupe et les sauve
    3° Je récupère le groupe
    -> Et tout est bon cette fois. Je dois donc sauver les articles avant le groupe qui le contient. Je ne vois pas trop la raison mais bon.. Je peux au moins continuer à avancer.

    L'un d'entre vous à t'il une explication sur ce phnéomène ?

    Merci

Discussions similaires

  1. Réponses: 4
    Dernier message: 18/06/2007, 08h30
  2. mapping de deux one-to-many
    Par emilie_caroline dans le forum Hibernate
    Réponses: 11
    Dernier message: 30/11/2006, 16h58
  3. [Hibernate] Relation one to many
    Par BRAUKRIS dans le forum Hibernate
    Réponses: 2
    Dernier message: 23/08/2006, 11h51
  4. [hibernate] relation one-to-many avec plusieurs clés
    Par seb_fou dans le forum Hibernate
    Réponses: 6
    Dernier message: 16/03/2006, 14h47
  5. [EJB2.1 Entity] [CMR] Relation One to Many
    Par hamed dans le forum Java EE
    Réponses: 2
    Dernier message: 31/12/2003, 14h26

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