2010-01-21 4 views
4

En supposant que les correspondances suivantes sont fournies:Est-il possible d'avoir une clé étrangère appliquée sans mappage objet-objet?

<class name="A" table="a_table"> 
    <id name="id"/> 
    <many-to-one name="entityB" column="fk_B" not-null="false" unique="true"/> 
</class> 

<class name="B" table="b_table"> 
    <id name="id"/> 
</class> 

classe Java:

public class A { 
    private long id; 
    private B entityB; 
    // getters and setters skipped 
} 

Est-il possible de changer le mapping Hibernate afin que clé étrangère est toujours appliquée et créé par Mise en veille prolongée lors du démarrage, mais la classe A ressemblerait à ce qui suit:

public class A { 
    private long id; 
    private long idOfB; 
    // getters and setters skipped 
} 

Je comprends que si je convertis <many-to-one... en <property... cela fonctionnerait, mais la clé étrangère ne serait pas appliquée par la base de données.

que je dois faire cela parce que l'objet B pourrait (ou non) être initialisé séparément, ce qui provoque parfois des exceptions org.hibernate.LazyInitializationException: could not initialize proxy - no Session se produire lorsque a.getB() est appelé. Je préférerais l'avoir comme long idOfB et charger l'objet entier chaque fois que c'est nécessaire; cela rendrait également le chargement de l'objet A plus rapide.

Je crois que ma question est très semblable à this one, mais la solution proposée (pour utiliser le chargement paresseux) ne convient pas dans mon cas, même si je l'appelle a.getB().getId(), je reçois LazyInitializationException alors si je l'appelle a.getIdOfB() je n » t.

Merci beaucoup d'avance.

+0

Je recommande fortement d'utiliser LazyLoading plutôt que de réinventer la roue. Vous obtiendrez des classes d'entités sécurisées, avec exactement les mêmes performances, et vous pourrez potentiellement supprimer le code de rechargement personnalisé. Notez que LazyLoading entraîne uniquement une exception LazyLoadingException si elle est utilisée de manière incorrecte, c'est-à-dire si la charge paresseuse est demandée après la fermeture de la session. Notez également que demander l'identifiant d'un objet n'entraîne pas le chargement de l'objet. Je vous recommande de poser une question avec les problèmes spécifiques que vous avez avec LazyLoading. – meriton

+0

Croyez-moi, j'utilise LazyLoading. C'est juste un cas sur des centaines où je ne peux pas. Sinon, je ne le demanderais pas. – mindas

+0

Question connexe: [java - Hibernate - Clés étrangères au lieu d'entités] (http://stackoverflow.com/questions/6311776/hibernate-foreign-keys-instead-of-entities). –

Répondre

7

Comme dit

Je comprends que si je convertir < many-to-one ... dans une propriété < ...cela fonctionnerait, mais la clé étrangère ne serait pas appliquée par la base de données.

Donc, mon conseil est: utilisation à la fois

public class EntityA { 

    private Integer idOfB; 

    private EntityB entityB; 

    // getter's and setter's 

} 

Et

<class name="A" table="a_table"> 
    <id name="id"/> 
    <property name="idOfB" column="fk_B" not-null="false" unique="true"/> 
    <many-to-one name="entityB" update="false" insert="false" column="fk_B"/> 
</class> 

Avis lorsque deux propriétés partagent la même colonne, vous devez mettre les paramètres à ce sujet en un propriété. Sinon, Hibernate va se plaindre de certaines erreurs. Il explique pourquoi je définis update = "false" et insert = "false" dans la propriété entityB.

salutations,

+0

Nice et lisse! Et ça marche ... – mindas

+0

Comment est-ce que j'accommoderais ceci avec jackson? – gabber12

4

Vous pouvez toujours créer la clé étrangère manuellement DDL dans votre mise en veille prolongée fichier hbm.xml:

<hibernate-mapping> 
    ... 
    <database-object> 
     <create>[CREATE FK]</create> 
     <drop>[DROP FK]</drop> 
    </database-object> 
</hibernate-mapping> 

Vous pouvez également portée cela si différents dialectes doivent être pris en charge.

Découvrez 5.7. Auxiliary database objects

0

Une autre approche que vous pourriez prendre est de définir le FK avec votre carte B plutôt que A la cartographie. J'ai ajouté le code JPA, vous devez le traduire dans votre fichier de mise en correspondance Hibernate si vous n'utilisez pas d'annotations.

@Entity 
public class B 
{ 
    private long id; 
    private List<A> aList; 

    @Id 
    @Column(name = "ID") 
    public long getId() 
    { 
     return id; 
    } 

    @OneToMany 
    @JoinColumn(name = "B_ID") 
    public List<A> getAList() 
    { 
     return aList; 
    } 
    public void setId(long id) 
    { 
     this.id = id; 
    } 
    public void setAList(List<A> aList) 
    { 
     this.aList = aList; 
    }   
} 

A.java ne ressembler à ceci:

@Entity 
public class A 
{ 
    private long id; 
    private long idOfB; 

    @Id 
    @Column(name = "ID") 
    public long getId() 
    { 
     return id; 
    } 
    @Column(name = "B_ID") 
    public long getIdOfB() 
    { 
     return idOfB; 
    } 
    public void setId(long id) 
    { 
     this.id = id; 
    } 
    public void setIdOfB(long idOfB) 
    { 
     this.idOfB = idOfB; 
    } 
} 
0

Je vous recommande d'associer des objets à des objets pour obtenir tous les avantages de la mise en veille prolongée. Je pense que le problème est l'exception que vous obtenez. C'est parce que la session Hibernate est déjà fermée lorsque vous essayez d'obtenir l'objet paresseux. Il y a plusieurs articles dans ce blog qui montrent les réponses à ce problème, par exemple celui-ci: link text.

Si vous utilisez Spring, vous pouvez utiliser OpenEntityManagerInViewFilter pour que la session reste ouverte jusqu'à ce que la vue soit affichée.

+0

Merci pour votre réponse, mais je suis pleinement conscient de pourquoi les exceptions de chargement paresseux sont jetés et comment les traiter. Cependant, c'est un cas particulier où j'aimerais que le cadre soit plus flexible et fasse le travail pour moi. Parce que c'est pourquoi ils sont écrits, n'est-ce pas? Enfin, je ne pense pas que ce que je demande soit trop pour un cadre de cartographie O-R, n'est-ce pas? – mindas

Questions connexes