-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 
Author Message
 Post subject: How map composite keys with hibernate ?
PostPosted: Fri Sep 09, 2011 12:01 pm 
Newbie

Joined: Fri Sep 09, 2011 6:09 am
Posts: 2
salut tout le monde,

J'ai un problème avec le mapping sous hibernate 3.3.1.GA.
J'ai deux tables sous Oracle définies comme ça:

    CREATE TABLE TABLE1
    (
    CLE1_ID NUMBER,
    CLE2_ID NUMBER,
    VALEUR1 NUMBER,
    CONSTRAINT PK1 PRIMARY KEY (CLE1_ID, CLE2_ID)
    );

    CREATE
    TABLE TABLE2
    (
    ID NUMBER,
    VALEUR2 NUMBER,
    CONSTRAINT PK2 PRIMARY KEY (ID)
    );

Je désire avoir le mappage sur deux classes la première qui référence la TABLE1 et la deuxième la TABLE2. La classe qui référence la TABLE1 doit avoir un attribut index composé d'un entier représenté par CLE1_ID et une référence à la classe qui référence la TABLE2 représenté par CLE2_ID.

Pour tester j'ai donc décidé de créer les classes suivantes (ces classes n'ont pas été exécutées, elles représentent les cas au j'ai été confronté pendant mes tentatives):

Cette classe génère une erreur de mapping. Elle cherche la colonne joinClass1 dans la table Table1.
La valeur name de l'annotation JoinColumn est totalement ignorée.
Code:
import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.Table;

@Entity
@Table(name = "Table1")
public class Class1 implements Serializable {
    private static final long serialVersionUID = -6762189798573234044L;

    @Id
    @Column(name = "cle1_id")
    private Integer id1;

    @Id
    @JoinColumn(name = "cle2_id")
    private JoinClass1 joinClass1;

    @Column(name = "valeur1")
    private Integer valeur;

    public Integer getId1() {
        return id1;
    }

    public void setId1(final Integer inId1) {
        id1 = inId1;
    }

    public JoinClass1 getJoinClass1() {
        return joinClass1;
    }

    public void setJoinClass1(final JoinClass1 inJoinClass1) {
        joinClass1 = inJoinClass1;
    }

    public Integer getValeur() {
        return valeur;
    }

    public void setValeur(final Integer inValeur) {
        valeur = inValeur;
    }
}


Cette classe marche correctement mais la valeur id2 m'est totalement inutile car elle doit être mappée sur la classe JoinClass1.
Code:
import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.Table;

@Entity
@Table(name = "Table1")
public class Class2 implements Serializable {
    private static final long serialVersionUID = -2647255052697251103L;

    @Id
    @Column(name = "cle1_id")
    private Integer id1;

    @Id
    @JoinColumn(name = "cle2_id")
    private Integer id2;

    @Column(name = "valeur1")
    private Integer valeur;

    public Integer getId1() {
        return id1;
    }

    public void setId1(final Integer inId1) {
        id1 = inId1;
    }

    public Integer getId2() {
        return id2;
    }

    public void setId2(final Integer inId2) {
        id2 = inId2;
    }

    public Integer getValeur() {
        return valeur;
    }

    public void setValeur(final Integer inValeur) {
        valeur = inValeur;
    }
}


Dans ce cas la recherche se fait avec une requête du style:

    SELECT cle1_id, cle2_id, joinClass1, valeur1 FROM TABLE1;

Ceci est incorrect car l'attribut joinClass1 est mappé sur cle2_id.
Code:
import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.Table;

@Entity
@Table(name = "Table1")
public class Class3 implements Serializable {
    private static final long serialVersionUID = 5341306667483897398L;

    @Id
    private EmbeddableClass1 id;

    @JoinColumn(name = "cle2_id", insertable = false, updatable = false)
    private JoinClass1 joinClass1;

    @Column(name = "valeur1")
    private Integer valeur;

    public EmbeddableClass1 getId() {
        return id;
    }

    public void setId(final EmbeddableClass1 inId) {
        id = inId;
    }

    public JoinClass1 getJoinClass1() {
        return joinClass1;
    }

    public void setJoinClass1(final JoinClass1 inJoinClass1) {
        joinClass1 = inJoinClass1;
    }

    public Integer getValeur() {
        return valeur;
    }

    public void setValeur(final Integer inValeur) {
        valeur = inValeur;
    }
}


Ici, la requête va se faire sur les colonnes cle1_id et joinClass1 et non sur cle1_id et cle2_id.
Code:
import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "Table1")
public class Class4 implements Serializable {
    private static final long serialVersionUID = -502323896966744414L;

    @Id
    private EmbeddableClass2 id;

    @Column(name = "valeur1")
    private Integer valeur;

    public EmbeddableClass2 getId() {
        return id;
    }

    public void setId(final EmbeddableClass2 inId) {
        id = inId;
    }

    public Integer getValeur() {
        return valeur;
    }

    public void setValeur(final Integer inValeur) {
        valeur = inValeur;
    }
}


La requête va se faire sur cle1_id et cle2_id (car @Id est placé après @JoinColumn) ce qui est correct mais j'obtient une erreur de serialisation.
Je suppose que hibernate s'attends à un entier et non à la classe JoinClass1 du coup il n'arrive pas a la déserialiser.
Code:
import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.Table;

@Entity
@Table(name = "Table1")
public class Class5 implements Serializable {
    private static final long serialVersionUID = -3957467786148845603L;

    @Column(name = "cle1_id")
    @Id
    private Integer id1;

    @JoinColumn(name = "cle2_id")
    @Id
    private JoinClass1 joinClass1;

    @Column(name = "valeur1")
    private Integer valeur;

    public Integer getId1() {
        return id1;
    }

    public void setId1(final Integer inId1) {
        id1 = inId1;
    }

    public JoinClass1 getJoinClass1() {
        return joinClass1;
    }

    public void setJoinClass1(final JoinClass1 inJoinClass1) {
        joinClass1 = inJoinClass1;
    }

    public Integer getValeur() {
        return valeur;
    }

    public void setValeur(final Integer inValeur) {
        valeur = inValeur;
    }
}


Code:
import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Embeddable;

@Embeddable
public class EmbeddableClass1 implements Serializable {
    private static final long serialVersionUID = 284252856199742376L;

    @Column(name = "cle1_id")
    private Integer id1;

    @Column(name = "cle2_id")
    private Integer id2;

    public Integer getId1() {
        return id1;
    }

    public void setId1(final Integer inId1) {
        id1 = inId1;
    }

    public Integer getId2() {
        return id2;
    }

    public void setId2(final Integer inId2) {
        id2 = inId2;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((id1 == null) ? 0 : id1.hashCode());
        result = prime * result + ((id2 == null) ? 0 : id2.hashCode());
        return result;
    }

    @Override
    public boolean equals(final Object inObj) {
        if (this == inObj) {
            return true;
        }
        if (inObj == null) {
            return false;
        }
        if (getClass() != inObj.getClass()) {
            return false;
        }
        EmbeddableClass1 other = (EmbeddableClass1) inObj;
        if (id1 == null) {
            if (other.id1 != null) {
                return false;
            }
        } else if (!id1.equals(other.id1)) {
            return false;
        }
        if (id2 == null) {
            if (other.id2 != null) {
                return false;
            }
        } else if (!id2.equals(other.id2)) {
            return false;
        }
        return true;
    }
}


Code:
import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Embeddable;
import javax.persistence.JoinColumn;

@Embeddable
public class EmbeddableClass2 implements Serializable {
    private static final long serialVersionUID = -8045903339967672727L;

    @Column(name = "cle1_id")
    private Integer id1;

    @JoinColumn(name = "cle2_id")
    private JoinClass1 joinClass1;

    public Integer getId1() {
        return id1;
    }

    public void setId1(final Integer inId1) {
        id1 = inId1;
    }

    public JoinClass1 getJoinClass1() {
        return joinClass1;
    }

    public void setJoinClass1(final JoinClass1 inJoinClass1) {
        joinClass1 = inJoinClass1;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((id1 == null) ? 0 : id1.hashCode());
        result = prime * result
                + ((joinClass1 == null) ? 0 : joinClass1.hashCode());
        return result;
    }

    @Override
    public boolean equals(final Object inObj) {
        if (this == inObj) {
            return true;
        }
        if (inObj == null) {
            return false;
        }
        if (getClass() != inObj.getClass()) {
            return false;
        }
        EmbeddableClass2 other = (EmbeddableClass2) inObj;
        if (id1 == null) {
            if (other.id1 != null) {
                return false;
            }
        } else if (!id1.equals(other.id1)) {
            return false;
        }
        if (joinClass1 == null) {
            if (other.joinClass1 != null) {
                return false;
            }
        } else if (!joinClass1.equals(other.joinClass1)) {
            return false;
        }
        return true;
    }
}


Code:
import java.io.Serializable;

@Entity
@Table(name = "Table2")
public class JoinClass1 implements Serializable {
    private static final long serialVersionUID = 1406546053858848808L;

    @Id
    @Column(name = "id")
    private Integer id;

    @Column(name = "valeur2")
    private Integer valeur;

    public Integer getId() {
        return id;
    }

    public void setId(final Integer inId) {
        id = inId;
    }

    public Integer getValeur() {
        return valeur;
    }

    public void setValeur(final Integer inValeur) {
        valeur = inValeur;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((id == null) ? 0 : id.hashCode());
        return result;
    }

    @Override
    public boolean equals(final Object inObj) {
        if (this == inObj) {
            return true;
        }
        if (inObj == null) {
            return false;
        }
        if (getClass() != inObj.getClass()) {
            return false;
        }
        JoinClass1 other = (JoinClass1) inObj;
        if (id == null) {
            if (other.id != null) {
                return false;
            }
        } else if (!id.equals(other.id)) {
            return false;
        }
        return true;
    }
}


Comment pouvoir utiliser une clé à valeur multiple en hibernate?
Ça me parait impossible qu'un tel cas ne soit pas prévu dans une librairie comme hibernate vu qu'il s'agit d'un cas de figure classique en base de données.

Leo


Last edited by leopoldog on Tue Sep 13, 2011 9:42 am, edited 1 time in total.

Top
 Profile  
 
 Post subject: Re: How map composite keys with hibernate ?
PostPosted: Tue Sep 13, 2011 9:41 am 
Newbie

Joined: Fri Sep 09, 2011 6:09 am
Posts: 2
Salut,

j'ai trouvé une solution au problème.

En pratique il s'agit d'utiliser la Class3 ou dans le JoinColumn on rajoute referencedColumnName="id" pour dire de mapper l'attribut id de la JoinClass1.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.